prepare release 1.13 (#2290)
* make voters a final class * upgrade dependencies * sort project alphabetically in dashboard widget * open detail page on row click * do not break on null tag name * added max height to scrollable widgets on dashboard * added timesheet duplicate event * allow to deactivate browser title update * improve comment box * moved role permissions to own menu * removed tabs in user screen * fix user can remove super-admin from own account
This commit is contained in:
@@ -157,7 +157,7 @@ class CustomerControllerTest extends ControllerBaseTest
|
||||
]);
|
||||
$this->assertIsRedirect($client, $this->createUrl('/admin/customer/1/details'));
|
||||
$client->followRedirect();
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box div.box-comments');
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .direct-chat-text');
|
||||
self::assertStringContainsString('<p>A beautiful and short comment <strong>with some</strong> markdown formatting</p>', $node->html());
|
||||
}
|
||||
|
||||
@@ -173,15 +173,15 @@ class CustomerControllerTest extends ControllerBaseTest
|
||||
]);
|
||||
$this->assertIsRedirect($client, $this->createUrl('/admin/customer/1/details'));
|
||||
$client->followRedirect();
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box div.box-comments');
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .direct-chat-msg');
|
||||
self::assertStringContainsString('Blah foo bar', $node->html());
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .box-comment a.confirmation-link');
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .box-body a.confirmation-link');
|
||||
self::assertEquals($this->createUrl('/admin/customer/1/comment_delete'), $node->attr('href'));
|
||||
|
||||
$this->request($client, '/admin/customer/1/comment_delete');
|
||||
$this->assertIsRedirect($client, $this->createUrl('/admin/customer/1/details'));
|
||||
$client->followRedirect();
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box div.box-comments');
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .box-body');
|
||||
self::assertStringContainsString('There were no comments posted yet', $node->html());
|
||||
}
|
||||
|
||||
@@ -197,15 +197,15 @@ class CustomerControllerTest extends ControllerBaseTest
|
||||
]);
|
||||
$this->assertIsRedirect($client, $this->createUrl('/admin/customer/1/details'));
|
||||
$client->followRedirect();
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box div.box-comments');
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .direct-chat-text');
|
||||
self::assertStringContainsString('Blah foo bar', $node->html());
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .box-comment a.btn.active');
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .direct-chat-text a.btn.active');
|
||||
self::assertEquals(0, $node->count());
|
||||
|
||||
$this->request($client, '/admin/customer/1/comment_pin');
|
||||
$this->assertIsRedirect($client, $this->createUrl('/admin/customer/1/details'));
|
||||
$client->followRedirect();
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .box-comment a.btn.active');
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .box-body a.btn.active');
|
||||
self::assertEquals(1, $node->count());
|
||||
self::assertEquals($this->createUrl('/admin/customer/1/comment_pin'), $node->attr('href'));
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ class PermissionControllerTest extends ControllerBaseTest
|
||||
$this->assertHasDataTable($client);
|
||||
$this->assertDataTableRowCount($client, 'datatable_user_admin_permissions', 119);
|
||||
$this->assertPageActions($client, [
|
||||
'back' => $this->createUrl('/admin/user/'),
|
||||
'roles modal-ajax-form' => $this->createUrl('/admin/permissions/roles/create'),
|
||||
//'back' => $this->createUrl('/admin/user/'),
|
||||
'create modal-ajax-form' => $this->createUrl('/admin/permissions/roles/create'),
|
||||
'help' => 'https://www.kimai.org/documentation/permissions.html'
|
||||
]);
|
||||
|
||||
|
||||
@@ -93,32 +93,20 @@ class ProfileControllerTest extends ControllerBaseTest
|
||||
|
||||
public function getTabTestData()
|
||||
{
|
||||
$userTabs = ['#settings', '#password', '#api-token'];
|
||||
|
||||
return [
|
||||
[User::ROLE_USER, UserFixtures::USERNAME_USER, ['#settings', '#password', '#api-token']],
|
||||
[User::ROLE_SUPER_ADMIN, UserFixtures::USERNAME_SUPER_ADMIN, array_merge($userTabs, ['#teams', '#roles'])],
|
||||
[User::ROLE_USER, UserFixtures::USERNAME_USER],
|
||||
[User::ROLE_SUPER_ADMIN, UserFixtures::USERNAME_SUPER_ADMIN],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTabTestData
|
||||
*/
|
||||
public function testEditActionTabs($role, $username, $expectedTabs)
|
||||
public function testEditActionTabs($role, $username)
|
||||
{
|
||||
$client = $this->getClientForAuthenticatedUser($role);
|
||||
$this->request($client, '/profile/' . $username . '/edit');
|
||||
$this->assertTrue($client->getResponse()->isSuccessful());
|
||||
|
||||
$tabs = $client->getCrawler()->filter('div.nav-tabs-custom ul.nav-tabs li');
|
||||
$this->assertEquals(\count($expectedTabs), $tabs->count());
|
||||
$foundTabs = [];
|
||||
|
||||
/** @var \DOMElement $tab */
|
||||
foreach ($tabs->filter('a') as $tab) {
|
||||
$foundTabs[] = $tab->getAttribute('href');
|
||||
}
|
||||
$this->assertEmpty(array_diff($expectedTabs, $foundTabs));
|
||||
}
|
||||
|
||||
public function testIndexActionWithDifferentUsername()
|
||||
|
||||
@@ -234,7 +234,7 @@ class ProjectControllerTest extends ControllerBaseTest
|
||||
]);
|
||||
$this->assertIsRedirect($client, $this->createUrl('/admin/project/1/details'));
|
||||
$client->followRedirect();
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box div.box-comments');
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .direct-chat-text');
|
||||
self::assertStringContainsString('<p>A beautiful and long comment <strong>with some</strong> markdown formatting</p>', $node->html());
|
||||
}
|
||||
|
||||
@@ -250,15 +250,15 @@ class ProjectControllerTest extends ControllerBaseTest
|
||||
]);
|
||||
$this->assertIsRedirect($client, $this->createUrl('/admin/project/1/details'));
|
||||
$client->followRedirect();
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box div.box-comments');
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .direct-chat-text');
|
||||
self::assertStringContainsString('Foo bar blub', $node->html());
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .box-comment a.confirmation-link');
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .box-body a.confirmation-link');
|
||||
self::assertEquals($this->createUrl('/admin/project/1/comment_delete'), $node->attr('href'));
|
||||
|
||||
$this->request($client, '/admin/project/1/comment_delete');
|
||||
$this->assertIsRedirect($client, $this->createUrl('/admin/project/1/details'));
|
||||
$client->followRedirect();
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box div.box-comments');
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .box-body');
|
||||
self::assertStringContainsString('There were no comments posted yet', $node->html());
|
||||
}
|
||||
|
||||
@@ -274,15 +274,15 @@ class ProjectControllerTest extends ControllerBaseTest
|
||||
]);
|
||||
$this->assertIsRedirect($client, $this->createUrl('/admin/project/1/details'));
|
||||
$client->followRedirect();
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box div.box-comments');
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .direct-chat-text');
|
||||
self::assertStringContainsString('Foo bar blub', $node->html());
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .box-comment a.btn.active');
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .box-body a.btn.active');
|
||||
self::assertEquals(0, $node->count());
|
||||
|
||||
$this->request($client, '/admin/project/1/comment_pin');
|
||||
$this->assertIsRedirect($client, $this->createUrl('/admin/project/1/details'));
|
||||
$client->followRedirect();
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .box-comment a.btn.active');
|
||||
$node = $client->getCrawler()->filter('div.box#comments_box .box-body a.btn.active');
|
||||
self::assertEquals(1, $node->count());
|
||||
self::assertEquals($this->createUrl('/admin/project/1/comment_pin'), $node->attr('href'));
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ class UserControllerTest extends ControllerBaseTest
|
||||
'search search-toggle visible-xs-inline' => '#',
|
||||
'visibility' => '#',
|
||||
'download toolbar-action' => $this->createUrl('/admin/user/export'),
|
||||
'permissions' => $this->createUrl('/admin/permissions'),
|
||||
'create' => $this->createUrl('/admin/user/create'),
|
||||
'help' => 'https://www.kimai.org/documentation/users.html'
|
||||
]);
|
||||
@@ -117,17 +116,6 @@ class UserControllerTest extends ControllerBaseTest
|
||||
$this->assertIsRedirect($client, $this->createUrl('/profile/' . urlencode($username) . '/edit'));
|
||||
$client->followRedirect();
|
||||
|
||||
$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());
|
||||
$foundTabs = [];
|
||||
/** @var \DOMElement $tab */
|
||||
foreach ($tabs->filter('a') as $tab) {
|
||||
$foundTabs[] = $tab->getAttribute('href');
|
||||
}
|
||||
$this->assertEmpty(array_diff($expectedTabs, $foundTabs));
|
||||
|
||||
$form = $client->getCrawler()->filter('form[name=user_edit]')->form();
|
||||
$this->assertEquals($username, $form->get('user_edit[alias]')->getValue());
|
||||
}
|
||||
|
||||
@@ -34,6 +34,9 @@ class TagTest extends TestCase
|
||||
$this->assertEquals('foo', $sut->getName());
|
||||
$this->assertEquals('foo', (string) $sut);
|
||||
|
||||
$sut->setName(null);
|
||||
$this->assertNull($sut->getName());
|
||||
|
||||
$this->assertInstanceOf(Tag::class, $sut->setColor('#fffccc'));
|
||||
$this->assertEquals('#fffccc', $sut->getColor());
|
||||
}
|
||||
|
||||
@@ -142,6 +142,7 @@ class UserTest extends TestCase
|
||||
public function testTeams()
|
||||
{
|
||||
$sut = new User();
|
||||
$user = new User();
|
||||
$team = new Team();
|
||||
self::assertEmpty($sut->getTeams());
|
||||
self::assertEmpty($team->getUsers());
|
||||
@@ -151,6 +152,10 @@ class UserTest extends TestCase
|
||||
self::assertSame($team, $sut->getTeams()[0]);
|
||||
self::assertSame($sut, $team->getUsers()[0]);
|
||||
self::assertTrue($sut->hasTeamAssignment());
|
||||
self::assertFalse($sut->hasTeamMember($user));
|
||||
|
||||
$team->addUser($user);
|
||||
self::assertTrue($sut->hasTeamMember($user));
|
||||
|
||||
self::assertFalse($sut->isTeamleadOf($team));
|
||||
self::assertTrue($sut->isInTeam($team));
|
||||
|
||||
35
tests/Event/TimesheetDuplicatePostEventTest.php
Normal file
35
tests/Event/TimesheetDuplicatePostEventTest.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Event;
|
||||
|
||||
use App\Entity\Timesheet;
|
||||
use App\Event\AbstractTimesheetEvent;
|
||||
use App\Event\TimesheetDuplicatePostEvent;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\TimesheetDuplicatePostEvent
|
||||
*/
|
||||
class TimesheetDuplicatePostEventTest extends AbstractTimesheetEventTest
|
||||
{
|
||||
protected function createTimesheetEvent(Timesheet $timesheet): AbstractTimesheetEvent
|
||||
{
|
||||
return new TimesheetDuplicatePostEvent($timesheet, new Timesheet());
|
||||
}
|
||||
|
||||
public function testGetOriginalTimesheet()
|
||||
{
|
||||
$newTimesheet = new Timesheet();
|
||||
$originalTimesheet = new Timesheet();
|
||||
$sut = new TimesheetDuplicatePostEvent($newTimesheet, $originalTimesheet);
|
||||
|
||||
self::assertSame($newTimesheet, $sut->getTimesheet());
|
||||
self::assertSame($originalTimesheet, $sut->getOriginalTimesheet());
|
||||
}
|
||||
}
|
||||
35
tests/Event/TimesheetDuplicatePreEventTest.php
Normal file
35
tests/Event/TimesheetDuplicatePreEventTest.php
Normal file
@@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Event;
|
||||
|
||||
use App\Entity\Timesheet;
|
||||
use App\Event\AbstractTimesheetEvent;
|
||||
use App\Event\TimesheetDuplicatePreEvent;
|
||||
|
||||
/**
|
||||
* @covers \App\Event\TimesheetDuplicatePreEvent
|
||||
*/
|
||||
class TimesheetDuplicatePreEventTest extends AbstractTimesheetEventTest
|
||||
{
|
||||
protected function createTimesheetEvent(Timesheet $timesheet): AbstractTimesheetEvent
|
||||
{
|
||||
return new TimesheetDuplicatePreEvent($timesheet, new Timesheet());
|
||||
}
|
||||
|
||||
public function testGetOriginalTimesheet()
|
||||
{
|
||||
$newTimesheet = new Timesheet();
|
||||
$originalTimesheet = new Timesheet();
|
||||
$sut = new TimesheetDuplicatePreEvent($newTimesheet, $originalTimesheet);
|
||||
|
||||
self::assertSame($newTimesheet, $sut->getTimesheet());
|
||||
self::assertSame($originalTimesheet, $sut->getOriginalTimesheet());
|
||||
}
|
||||
}
|
||||
@@ -40,7 +40,7 @@ class UserPreferenceSubscriberTest extends TestCase
|
||||
self::assertSame($user, $event->getUser());
|
||||
|
||||
$prefs = $sut->getDefaultPreferences($user);
|
||||
self::assertCount(12, $prefs);
|
||||
self::assertCount(13, $prefs);
|
||||
|
||||
foreach ($prefs as $pref) {
|
||||
switch ($pref->getName()) {
|
||||
@@ -70,7 +70,7 @@ class UserPreferenceSubscriberTest extends TestCase
|
||||
// TODO test merging values
|
||||
$sut->loadUserPreferences($event);
|
||||
$prefs = $event->getUser()->getPreferences();
|
||||
self::assertCount(12, $prefs);
|
||||
self::assertCount(13, $prefs);
|
||||
|
||||
foreach ($prefs as $pref) {
|
||||
switch ($pref->getName()) {
|
||||
|
||||
30
tests/Utils/AvatarServiceTest.php
Normal file
30
tests/Utils/AvatarServiceTest.php
Normal file
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Kimai time-tracking app.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
namespace App\Tests\Utils;
|
||||
|
||||
use App\Utils\AvatarService;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Utils\AvatarService
|
||||
*/
|
||||
class AvatarServiceTest extends TestCase
|
||||
{
|
||||
public function testDataDirectory()
|
||||
{
|
||||
$data = realpath(__DIR__ . '/../../');
|
||||
$sut = new AvatarService($data);
|
||||
self::assertEquals($data . '/public/avatars', $sut->getStorageDirectory());
|
||||
|
||||
$data = realpath(__DIR__ . '/../../var/data/');
|
||||
$sut->setStorageDirectory($data);
|
||||
self::assertEquals($data, $sut->getStorageDirectory());
|
||||
}
|
||||
}
|
||||
@@ -39,4 +39,19 @@ class FileHelperTest extends TestCase
|
||||
{
|
||||
self::assertEquals($expected, FileHelper::convertToAsciiFilename($original));
|
||||
}
|
||||
|
||||
public function testDataDirectory()
|
||||
{
|
||||
$data = realpath(__DIR__ . '/../_data/');
|
||||
$sut = new FileHelper($data);
|
||||
self::assertEquals($data . '/', $sut->getDataDirectory());
|
||||
self::assertEquals($data . '/foo/', $sut->getDataDirectory('/foo/'));
|
||||
self::assertEquals($data . '/foo/', $sut->getDataDirectory('foo'));
|
||||
|
||||
$data = realpath(__DIR__ . '/../../var/data/');
|
||||
$sut->setDataDirectory($data);
|
||||
self::assertEquals($data . '/', $sut->getDataDirectory());
|
||||
self::assertEquals($data . '/foo/', $sut->getDataDirectory('/foo/'));
|
||||
self::assertEquals($data . '/foo/', $sut->getDataDirectory('foo'));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user