configurable csv/xlsx export templates (#5531)
This commit is contained in:
61
tests/Form/ExportTemplateSpreadsheetFormTest.php
Normal file
61
tests/Form/ExportTemplateSpreadsheetFormTest.php
Normal file
@@ -0,0 +1,61 @@
|
||||
<?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\Form;
|
||||
|
||||
use App\Configuration\LocaleService;
|
||||
use App\Entity\ExportTemplate;
|
||||
use App\Form\ExportTemplateSpreadsheetForm;
|
||||
use App\Form\Type\ExportColumnsType;
|
||||
use App\Form\Type\LanguageType;
|
||||
use Psr\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Form\FormTypeInterface;
|
||||
use Symfony\Component\Form\Test\TypeTestCase;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* @covers \App\Form\ExportTemplateSpreadsheetForm
|
||||
*/
|
||||
class ExportTemplateSpreadsheetFormTest extends TypeTestCase
|
||||
{
|
||||
/**
|
||||
* @return FormTypeInterface[]
|
||||
*/
|
||||
protected function getTypes(): array // @phpstan-ignore missingType.generics
|
||||
{
|
||||
$dispatcher = $this->createMock(EventDispatcherInterface::class);
|
||||
$translator = $this->createMock(TranslatorInterface::class);
|
||||
|
||||
return [
|
||||
new ExportColumnsType($dispatcher, $translator),
|
||||
new LanguageType(new LocaleService([]))
|
||||
];
|
||||
}
|
||||
|
||||
public function testWithGlobalNewActivity(): void
|
||||
{
|
||||
$model = new ExportTemplate();
|
||||
$form = $this->factory->createBuilder(ExportTemplateSpreadsheetForm::class, $model);
|
||||
|
||||
$attr = $form->getFormConfig()->getOption('attr');
|
||||
self::assertIsArray($attr);
|
||||
self::assertArrayHasKey('data-form-event', $attr);
|
||||
self::assertEquals('kimai.exportTemplate', $attr['data-form-event']);
|
||||
|
||||
self::assertTrue($form->has('title'));
|
||||
self::assertTrue($form->has('renderer'));
|
||||
self::assertTrue($form->has('language'));
|
||||
self::assertTrue($form->has('columns'));
|
||||
|
||||
self::assertTrue($form->get('title')->getRequired());
|
||||
self::assertTrue($form->get('renderer')->getRequired());
|
||||
self::assertFalse($form->get('language')->getRequired());
|
||||
self::assertTrue($form->get('columns')->getRequired());
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,8 @@ namespace App\Tests\Form\Extension;
|
||||
use App\Form\Extension\DocumentationLinkExtension;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\Exception\InvalidOptionsException;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
@@ -43,4 +45,18 @@ class DocumentationLinkExtensionTest extends TestCase
|
||||
$this->expectException(InvalidOptionsException::class);
|
||||
$resolver->resolve(['docu_chapter' => true]);
|
||||
}
|
||||
|
||||
public function testBuildView(): void
|
||||
{
|
||||
$sut = new DocumentationLinkExtension();
|
||||
$form = $this->createMock(FormInterface::class);
|
||||
|
||||
$view = new FormView();
|
||||
$sut->buildView($view, $form, ['docu_chapter' => null]);
|
||||
self::assertEquals(['attr' => [], 'value' => null, 'docu_chapter' => null], $view->vars);
|
||||
|
||||
$view = new FormView();
|
||||
$sut->buildView($view, $form, ['docu_chapter' => 'customers']);
|
||||
self::assertEquals(['attr' => [], 'value' => null, 'docu_chapter' => 'customers'], $view->vars);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,8 @@ use App\Form\Extension\EnhancedChoiceTypeExtension;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Bridge\Doctrine\Form\Type\EntityType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\ChoiceType;
|
||||
use Symfony\Component\Form\FormInterface;
|
||||
use Symfony\Component\Form\FormView;
|
||||
use Symfony\Component\OptionsResolver\OptionsResolver;
|
||||
|
||||
/**
|
||||
@@ -30,15 +32,52 @@ class EnhancedChoiceTypeExtensionTest extends TestCase
|
||||
$resolver = new OptionsResolver();
|
||||
$sut = new EnhancedChoiceTypeExtension();
|
||||
$sut->configureOptions($resolver);
|
||||
self::assertEquals(['selectpicker', 'width', 'search'], $resolver->getDefinedOptions());
|
||||
self::assertEquals(['selectpicker', 'width', 'search', 'order'], $resolver->getDefinedOptions());
|
||||
self::assertTrue($resolver->hasDefault('selectpicker'));
|
||||
self::assertTrue($resolver->hasDefault('width'));
|
||||
self::assertTrue($resolver->hasDefault('search'));
|
||||
self::assertTrue($resolver->hasDefault('order'));
|
||||
self::assertFalse($resolver->isRequired('selectpicker'));
|
||||
self::assertFalse($resolver->isRequired('width'));
|
||||
self::assertFalse($resolver->isRequired('search'));
|
||||
|
||||
$result = $resolver->resolve([]);
|
||||
self::assertEquals(['selectpicker' => true, 'width' => '100%', 'search' => true], $result);
|
||||
self::assertEquals(['selectpicker' => true, 'width' => '100%', 'search' => true, 'order' => false], $result);
|
||||
}
|
||||
|
||||
public static function getTestData(): iterable
|
||||
{
|
||||
yield [
|
||||
['expanded' => true],
|
||||
['value' => null, 'attr' => []]
|
||||
];
|
||||
|
||||
yield [
|
||||
['multiple' => false, 'width' => false, 'search' => true, 'selectpicker' => true, 'order', 'required' => false],
|
||||
['value' => null, 'attr' => ['class' => 'selectpicker']]
|
||||
];
|
||||
|
||||
yield [
|
||||
['multiple' => false, 'width' => '100%', 'search' => true, 'required' => false, 'order' => true],
|
||||
['value' => null, 'attr' => ['class' => 'selectpicker', 'data-width' => '100%', 'data-order' => 1]]
|
||||
];
|
||||
|
||||
yield [
|
||||
['multiple' => true, 'width' => '50%', 'search' => false, 'required' => true, 'attr' => []],
|
||||
['value' => null, 'attr' => ['size' => 1, 'class' => 'selectpicker', 'data-width' => '50%', 'data-disable-search' => 1, 'required' => 'required', 'placeholder' => '']]
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTestData
|
||||
*/
|
||||
public function testBuildView(array $options, array $expected): void
|
||||
{
|
||||
$sut = new EnhancedChoiceTypeExtension();
|
||||
$view = new FormView();
|
||||
$form = $this->createMock(FormInterface::class);
|
||||
|
||||
$sut->buildView($view, $form, $options);
|
||||
self::assertEquals($expected, $view->vars);
|
||||
}
|
||||
}
|
||||
|
||||
72
tests/Form/Type/ExportColumnsTypeTest.php
Normal file
72
tests/Form/Type/ExportColumnsTypeTest.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?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\Form\Type;
|
||||
|
||||
use App\Form\Type\ExportColumnsType;
|
||||
use App\Tests\Mocks\MetaFieldColumnSubscriberMock;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||
use Symfony\Component\Form\Test\TypeTestCase;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
/**
|
||||
* @covers \App\Form\Type\ExportColumnsType
|
||||
*/
|
||||
class ExportColumnsTypeTest extends TypeTestCase
|
||||
{
|
||||
public static function getTestData(): iterable
|
||||
{
|
||||
yield [['foo', 'bar'], []];
|
||||
|
||||
yield [
|
||||
['user.name', 'customer.meta.customer-foo', 'duration', 'hello', 'user.meta.mypref'],
|
||||
['user.name', 'customer.meta.customer-foo', 'duration', 'user.meta.mypref']
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return ExportColumnsType[]
|
||||
*/
|
||||
protected function getTypes(): array
|
||||
{
|
||||
$dispatcher = new EventDispatcher();
|
||||
$dispatcher->addSubscriber(new MetaFieldColumnSubscriberMock());
|
||||
|
||||
$translator = $this->createMock(TranslatorInterface::class);
|
||||
|
||||
return [
|
||||
new ExportColumnsType($dispatcher, $translator)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<mixed> $value
|
||||
* @param array<mixed> $expected
|
||||
* @dataProvider getTestData
|
||||
*/
|
||||
public function testSubmitValidData(array $value, array $expected): void
|
||||
{
|
||||
$data = ['columns' => $value];
|
||||
$model = new TypeTestModel(['columns' => []]);
|
||||
|
||||
$form = $this->factory->createBuilder(FormType::class, $model);
|
||||
$form->add('columns', ExportColumnsType::class);
|
||||
$form = $form->getForm();
|
||||
|
||||
$expected = new TypeTestModel([
|
||||
'columns' => $expected
|
||||
]);
|
||||
|
||||
$form->submit($data);
|
||||
|
||||
self::assertTrue($form->isSynchronized());
|
||||
self::assertEquals($expected, $model);
|
||||
}
|
||||
}
|
||||
51
tests/Form/Type/ExportRendererTypeTest.php
Normal file
51
tests/Form/Type/ExportRendererTypeTest.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\Form\Type;
|
||||
|
||||
use App\Form\Type\ExportRendererType;
|
||||
use Symfony\Component\Form\Extension\Core\Type\FormType;
|
||||
use Symfony\Component\Form\Test\TypeTestCase;
|
||||
|
||||
/**
|
||||
* @covers \App\Form\Type\ExportRendererType
|
||||
*/
|
||||
class ExportRendererTypeTest extends TypeTestCase
|
||||
{
|
||||
public static function getTestData(): iterable
|
||||
{
|
||||
yield ['foo', null];
|
||||
yield ['csv', 'csv'];
|
||||
yield ['csV', null];
|
||||
yield ['xlsx', 'xlsx'];
|
||||
yield ['XLSX', null];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider getTestData
|
||||
*/
|
||||
public function testSubmitValidData(string $value, string|null $expected): void
|
||||
{
|
||||
$data = ['renderer' => $value];
|
||||
$model = new TypeTestModel(['renderer' => null]);
|
||||
|
||||
$form = $this->factory->createBuilder(FormType::class, $model);
|
||||
$form->add('renderer', ExportRendererType::class);
|
||||
$form = $form->getForm();
|
||||
|
||||
$expected = new TypeTestModel([
|
||||
'renderer' => $expected
|
||||
]);
|
||||
|
||||
$form->submit($data);
|
||||
|
||||
self::assertTrue($form->isSynchronized());
|
||||
self::assertEquals($expected, $model);
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ namespace App\Tests\Form\Type;
|
||||
*/
|
||||
class TypeTestModel extends \ArrayObject
|
||||
{
|
||||
public function __set(string $name, string|int|null $value)
|
||||
public function __set(string $name, string|int|null|array $value)
|
||||
{
|
||||
$this->offsetSet($name, $value);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user