added plugin screen (#671)

This commit is contained in:
Kevin Papst
2019-04-08 18:38:56 +02:00
committed by GitHub
parent 5bea9915f5
commit 3a4aa5a001
68 changed files with 1392 additions and 490 deletions

View File

@@ -31,10 +31,10 @@ class ConfigurationControllerTest extends APIControllerBaseTest
$this->assertIsArray($result);
$this->assertNotEmpty($result);
$this->assertEquals(7, count($result));
$this->assertStructure($result, false);
$this->assertStructure($result);
}
protected function assertStructure(array $result, $full = true)
protected function assertStructure(array $result)
{
$expectedKeys = ['date', 'date_time', 'duration', 'form_date', 'form_date_time', 'is24hours', 'time'];
$actual = array_keys($result);

View File

@@ -29,9 +29,9 @@ class AboutControllerTest extends ControllerBaseTest
$this->assertAccessIsGranted($client, '/admin/about');
$result = $client->getCrawler()->filter('div.nav-tabs-custom ul.nav.nav-tabs li');
$this->assertEquals(3, count($result));
$this->assertEquals(2, count($result));
$result = $client->getCrawler()->filter('div.nav-tabs-custom div.tab-content div.tab-pane');
$this->assertEquals(3, count($result));
$this->assertEquals(2, count($result));
}
}

View File

@@ -31,6 +31,7 @@ class CalendarControllerTest extends ControllerBaseTest
$crawler = $client->getCrawler();
$calendar = $crawler->filter('div#calendar');
$this->assertEquals(1, $calendar->count());
}
public function testCalendarEntriesAction()

View File

@@ -202,6 +202,23 @@ abstract class ControllerBaseTest extends WebTestCase
$this->assertEquals($count, $node->count());
}
/**
* @param Client $client
* @param array $buttons
*/
protected function assertPageActions(Client $client, array $buttons)
{
$node = $client->getCrawler()->filter('section.content-header div.breadcrumb div.box-tools div.btn-group a.btn');
$this->assertEquals(count($buttons), $node->count());
foreach ($node->getIterator() as $element) {
$expectedClass = str_replace('btn btn-default btn-', '', $element->getAttribute('class'));
$this->assertArrayHasKey($expectedClass, $buttons);
$expectedUrl = $buttons[$expectedClass];
$this->assertEquals($expectedUrl, $element->getAttribute('href'));
}
}
/**
* @param string $role the USER role to use for the request
* @param string $url the URL of the page displaying the initial form to submit

View File

@@ -40,7 +40,6 @@ class ExportControllerTest extends ControllerBaseTest
$em = $client->getContainer()->get('doctrine.orm.entity_manager');
$begin = new \DateTime('first day of this month');
$end = new \DateTime('last day of this month');
$fixture = new TimesheetFixtures();
$fixture
->setUser($this->getUserByRole($em, User::ROLE_USER))

View File

@@ -0,0 +1,48 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Tests\Controller;
use App\Entity\User;
use App\Plugin\PluginManager;
use App\Tests\Plugin\Fixtures\TestPlugin;
/**
* @coversDefaultClass \App\Controller\PluginController
* @group integration
*/
class PluginControllerTest extends ControllerBaseTest
{
public function testIsSecure()
{
$this->assertUrlIsSecured('/admin/plugins/');
$this->assertUrlIsSecuredForRole(User::ROLE_ADMIN, '/admin/plugins/');
}
public function testIndexAction()
{
$client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN);
$this->assertAccessIsGranted($client, '/admin/plugins/');
$this->assertCalloutWidgetWithMessage($client, 'You have no plugin installed yet');
$this->assertPageActions($client, ['shop' => 'https://www.kimai.org/store/']);
}
public function testIndexActionWithInstalledPlugins()
{
$client = $this->getClientForAuthenticatedUser(User::ROLE_SUPER_ADMIN);
/** @var PluginManager $manager */
$manager = self::$container->get(PluginManager::class);
$manager->addPlugin(new TestPlugin());
$this->assertAccessIsGranted($client, '/admin/plugins/');
$this->assertHasDataTable($client);
$this->assertDataTableRowCount($client, 'datatable_plugins', 1);
}
}

View File

@@ -11,7 +11,7 @@ namespace App\Tests\Export\Renderer;
use App\Export\Renderer\HtmlRenderer;
use Symfony\Component\HttpFoundation\Request;
use Twig\Loader\FilesystemLoader;
use Twig\Environment;
/**
* @covers \App\Export\Renderer\HtmlRenderer
@@ -22,7 +22,7 @@ class HtmlRendererTest extends AbstractRendererTest
public function testConfiguration()
{
$sut = new HtmlRenderer(
$this->getMockBuilder(\Twig_Environment::class)->disableOriginalConstructor()->getMock()
$this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock()
);
$this->assertEquals('html', $sut->getId());
@@ -33,16 +33,13 @@ class HtmlRendererTest extends AbstractRendererTest
public function testRender()
{
$kernel = self::bootKernel();
/** @var \Twig_Environment $twig */
/** @var Environment $twig */
$twig = $kernel->getContainer()->get('twig');
$stack = $kernel->getContainer()->get('request_stack');
$request = new Request();
$request->setLocale('en');
$stack->push($request);
/** @var FilesystemLoader $loader */
$loader = $twig->getLoader();
$sut = new HtmlRenderer($twig);
$response = $this->render($sut);

View File

@@ -19,7 +19,7 @@ use App\Utils\MPdfConverter;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken;
use Twig\Loader\FilesystemLoader;
use Twig\Environment;
/**
* @covers \App\Export\Renderer\PDFRenderer
@@ -45,7 +45,7 @@ class PdfRendererTest extends AbstractRendererTest
public function testConfiguration()
{
$sut = new PDFRenderer(
$this->getMockBuilder(\Twig_Environment::class)->disableOriginalConstructor()->getMock(),
$this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock(),
$this->getDateTimeFactory(),
$this->getMockBuilder(HtmlToPdfConverter::class)->getMock()
);
@@ -58,7 +58,7 @@ class PdfRendererTest extends AbstractRendererTest
public function testRender()
{
$kernel = self::bootKernel();
/** @var \Twig_Environment $twig */
/** @var Environment $twig */
$twig = $kernel->getContainer()->get('twig');
$stack = $kernel->getContainer()->get('request_stack');
$cacheDir = $kernel->getContainer()->getParameter('kernel.cache_dir');
@@ -67,9 +67,6 @@ class PdfRendererTest extends AbstractRendererTest
$request->setLocale('en');
$stack->push($request);
/** @var FilesystemLoader $loader */
$loader = $twig->getLoader();
$sut = new PDFRenderer($twig, $this->getDateTimeFactory(), $converter);
$response = $this->render($sut);

View File

@@ -12,6 +12,7 @@ namespace App\Tests\Export;
use App\Export\Renderer\HtmlRenderer;
use App\Export\ServiceExport;
use PHPUnit\Framework\TestCase;
use Twig\Environment;
/**
* @covers \App\Export\ServiceExport
@@ -20,22 +21,22 @@ class ServiceExportTest extends TestCase
{
public function testEmptyObject()
{
$sut = new ServiceExport();
$sut = new ServiceExport([]);
$this->assertEmpty($sut->getRenderer());
}
public function testUnknownRendererReturnsNull()
{
$sut = new ServiceExport();
$sut = new ServiceExport([]);
$this->assertNull($sut->getRendererById('default'));
}
public function testAdd()
{
$sut = new ServiceExport();
$sut = new ServiceExport([]);
$sut->addRenderer(new HtmlRenderer(
$this->getMockBuilder(\Twig_Environment::class)->disableOriginalConstructor()->getMock()
$this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock()
));
$this->assertEquals(1, count($sut->getRenderer()));

View File

@@ -11,6 +11,7 @@ namespace App\Tests\Invoice\Renderer;
use App\Invoice\Renderer\TwigRenderer;
use Symfony\Component\HttpFoundation\Request;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;
/**
@@ -21,7 +22,7 @@ class TwigRendererTest extends AbstractRendererTest
public function testSupports()
{
$loader = new FilesystemLoader();
$env = new \Twig_Environment($loader);
$env = new Environment($loader);
$sut = new TwigRenderer($env);
$this->assertTrue($sut->supports($this->getInvoiceDocument('default.html.twig')));
@@ -37,7 +38,7 @@ class TwigRendererTest extends AbstractRendererTest
public function testRender()
{
$kernel = self::bootKernel();
/** @var \Twig_Environment $twig */
/** @var Environment $twig */
$twig = $kernel->getContainer()->get('twig');
$stack = $kernel->getContainer()->get('request_stack');
$request = new Request();

View File

@@ -16,6 +16,7 @@ use App\Invoice\Renderer\TwigRenderer;
use App\Invoice\ServiceInvoice;
use App\Repository\InvoiceDocumentRepository;
use PHPUnit\Framework\TestCase;
use Twig\Environment;
/**
* @covers \App\Invoice\ServiceInvoice
@@ -65,7 +66,7 @@ class ServiceInvoiceTest extends TestCase
$sut->addNumberGenerator(new DateNumberGenerator());
$sut->addRenderer(
new TwigRenderer(
$this->getMockBuilder(\Twig_Environment::class)->disableOriginalConstructor()->getMock()
$this->getMockBuilder(Environment::class)->disableOriginalConstructor()->getMock()
)
);

View File

@@ -0,0 +1,31 @@
<?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\Plugin\Fixtures;
use App\Plugin\PluginInterface;
class TestPlugin implements PluginInterface
{
/**
* @return string
*/
public function getName()
{
return 'TestPlugin';
}
/**
* @return string
*/
public function getPath()
{
return __DIR__;
}
}

View File

@@ -0,0 +1,29 @@
{
"name": "kimai/test-plugin-composer",
"description": "Just a test fixture for the PluginManager",
"homepage": "https://github.com/kevinpapst/kimai2",
"type": "kimai-plugin",
"require": {
"kimai/kimai2-composer": "*",
"kevinpapst/kimai2": "*"
},
"keywords": [
"kimai",
"kimai-plugin"
],
"license": "proprietary",
"authors": [
{
"name": "Kevin Papst",
"homepage": "https://www.kevinpapst.de"
}
],
"extra": {
"kimai": {
"require": "0.9",
"version": "1.0",
"name": "TestPlugin from composer.json",
"license": []
}
}
}

View File

@@ -0,0 +1,78 @@
<?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\Plugin;
use App\Plugin\Plugin;
use App\Plugin\PluginInterface;
use App\Plugin\PluginManager;
use App\Plugin\PluginMetadata;
use App\Tests\Plugin\Fixtures\TestPlugin;
use PHPUnit\Framework\TestCase;
/**
* @covers \App\Plugin\PluginManager
*/
class PluginManagerTest extends TestCase
{
public function testEmptyObject()
{
$sut = new PluginManager([]);
$this->assertEmpty($sut->getPlugins());
$this->assertNull($sut->getPlugin('foo'));
}
public function testUnknownRendererReturnsNull()
{
$sut = new PluginManager([]);
$this->assertNull($sut->getPlugin('foo'));
}
public function testAdd()
{
$sut = new PluginManager([]);
$plugin = $this->getMockBuilder(PluginInterface::class)
->setMethods(['getName', 'getPath'])
->getMock();
$plugin->method('getName')->willReturn('foo');
$plugin->method('getPath')->willReturn('bar');
$sut->addPlugin(new TestPlugin());
$sut->addPlugin($plugin);
$sut->addPlugin(new TestPlugin());
// make sure a plugin with the same name is not added twice, the first one wins!
$this->assertEquals(2, count($sut->getPlugins()));
$foo = $sut->getPlugin('foo');
$this->assertInstanceOf(Plugin::class, $foo);
$this->assertEquals('foo', $foo->getName());
$this->assertEquals('bar', $foo->getPath());
$test = $sut->getPlugin('TestPlugin');
$this->assertInstanceOf(Plugin::class, $test);
$this->assertEquals('TestPlugin', $test->getName());
$this->assertEquals(new PluginMetadata(), $test->getMetadata());
}
public function testLoadMetadata()
{
$sut = new PluginManager([new TestPlugin()]);
$plugin = $sut->getPlugin('TestPlugin');
$sut->loadMetadata($plugin);
$meta = $plugin->getMetadata();
$this->assertEquals('0.9', $meta->getKimaiVersion());
$this->assertEquals('1.0', $meta->getVersion());
$this->assertEquals('Just a test fixture for the PluginManager', $meta->getDescription());
$this->assertEquals('https://github.com/kevinpapst/kimai2', $meta->getHomepage());
}
}

View File

@@ -0,0 +1,42 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Tests\Plugin;
use App\Plugin\PluginMetadata;
use PHPUnit\Framework\TestCase;
/**
* @covers \App\Plugin\PluginMetadata
*/
class PluginMetadataTest extends TestCase
{
public function testEmptyObject()
{
$sut = new PluginMetadata();
$this->assertNull($sut->getDescription());
$this->assertNull($sut->getHomepage());
$this->assertNull($sut->getVersion());
$this->assertNull($sut->getKimaiVersion());
}
public function testGetterAndSetter()
{
$sut = new PluginMetadata();
$this->assertInstanceOf(PluginMetadata::class, $sut->setVersion('13.7'));
$this->assertInstanceOf(PluginMetadata::class, $sut->setHomepage('http://www.example.com'));
$this->assertInstanceOf(PluginMetadata::class, $sut->setDescription('foo bar'));
$this->assertInstanceOf(PluginMetadata::class, $sut->setKimaiVersion('1.0'));
$this->assertEquals('13.7', $sut->getVersion());
$this->assertEquals('http://www.example.com', $sut->getHomepage());
$this->assertEquals('foo bar', $sut->getDescription());
$this->assertEquals('1.0', $sut->getKimaiVersion());
}
}

View File

@@ -0,0 +1,48 @@
<?php
/*
* This file is part of the Kimai time-tracking app.
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Tests\Plugin;
use App\Plugin\Plugin;
use App\Plugin\PluginMetadata;
use PHPUnit\Framework\TestCase;
/**
* @covers \App\Plugin\Plugin
*/
class PluginTest extends TestCase
{
public function testEmptyObject()
{
$plugin = new Plugin();
$this->assertNull($plugin->getName());
$this->assertNull($plugin->getPath());
$this->assertNull($plugin->getMetadata());
}
public function testGetterAndSetter()
{
$metadata = new PluginMetadata();
$metadata
->setDescription('foo')
->setHomepage('http://www.example.com')
->setVersion('13.7')
->setKimaiVersion('1.1')
;
$plugin = new Plugin();
$this->assertInstanceOf(Plugin::class, $plugin->setName('foo'));
$this->assertInstanceOf(Plugin::class, $plugin->setPath('bar'));
$this->assertInstanceOf(Plugin::class, $plugin->setMetadata($metadata));
$this->assertEquals('foo', $plugin->getName());
$this->assertEquals('bar', $plugin->getPath());
$this->assertSame($metadata, $plugin->getMetadata());
}
}

View File

@@ -19,6 +19,7 @@ use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\Intl\Util\IntlTestHelper;
use Twig\TwigFilter;
use Twig\TwigFunction;
/**
* @covers \App\Twig\Extensions
@@ -68,7 +69,7 @@ class ExtensionsTest extends TestCase
$this->assertCount(count($functions), $twigFunctions);
$i = 0;
foreach ($twigFunctions as $filter) {
$this->assertInstanceOf(\Twig_SimpleFunction::class, $filter);
$this->assertInstanceOf(TwigFunction::class, $filter);
$this->assertEquals($functions[$i++], $filter->getName());
}
}