Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,6 @@ yarn-error.log
###> vincentlanglet/twig-cs-fixer ###
/.twig-cs-fixer.cache
###< vincentlanglet/twig-cs-fixer ###

# Generated by Symfony when the test application boots
/tests/App/config/reference.php
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ Latest
------

## Changes
* [#81](https://github.com/cleverage/ui-process-bundle/issues/81) Add missing tests: functional tests of the UI and the HTTP API on a test application (SQLite, in-memory Messenger), unit tests of every class (DI, command, migrations, entities, managers, message handlers, scheduler, Monolog handlers, forms, EasyAdmin fields and filters, Twig, validators); `memory_limit` set to 512M for the test suite.
* [#83](https://github.com/cleverage/ui-process-bundle/issues/83) Remove `UploadAndExecuteAction` (route `process_upload_and_execute`), `ProcessUploadFileType` and `ProcessConfigurationValueResolver`: the action was broken and unreachable, file uploads are handled by `LaunchAction` (`entrypoint_type: file`).
* [#84](https://github.com/cleverage/ui-process-bundle/issues/84) Add `LogRecord::hasContextInfo()`, deprecate the misnamed `LogRecord::contextIsEmpty()` (it returns `true` when the context is not empty). Add tests.
* [#85](https://github.com/cleverage/ui-process-bundle/issues/85) `ProcessHandler`: default report increment level aligned on the bundle configuration (`Warning`); declare the `symfony/ux-twig-component` dependency. Add tests.
Expand Down
4 changes: 4 additions & 0 deletions phpunit.xml.dist
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@
<directory>tests</directory>
</testsuite>
</testsuites>
<php>
<!-- The functional tests boot the test application (EasyAdmin, Doctrine...) -->
<ini name="memory_limit" value="512M"/>
</php>
<source>
<include>
<directory suffix=".php">src</directory>
Expand Down
44 changes: 44 additions & 0 deletions tests/Admin/Field/ContextFieldTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

/*
* This file is part of the CleverAge/UiProcessBundle package.
*
* Copyright (c) Clever-Age
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace CleverAge\UiProcessBundle\Tests\Admin\Field;

use CleverAge\UiProcessBundle\Admin\Field\ContextField;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Translation\TranslatableMessage;

#[CoversClass(ContextField::class)]
class ContextFieldTest extends TestCase
{
public function testNew(): void
{
$dto = ContextField::new('myProperty', 'My label')->getAsDto();

self::assertSame('myProperty', $dto->getProperty());
self::assertSame('My label', $dto->getLabel());
self::assertSame('@CleverAgeUiProcess/admin/field/array.html.twig', $dto->getTemplatePath());
}

public function testNewWithTranslatableLabel(): void
{
$label = new TranslatableMessage('my.label');

self::assertSame($label, ContextField::new('myProperty', $label)->getAsDto()->getLabel());
}

public function testNewWithoutLabel(): void
{
self::assertNull(ContextField::new('myProperty')->getAsDto()->getLabel());
}
}
44 changes: 44 additions & 0 deletions tests/Admin/Field/EnumFieldTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

/*
* This file is part of the CleverAge/UiProcessBundle package.
*
* Copyright (c) Clever-Age
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace CleverAge\UiProcessBundle\Tests\Admin\Field;

use CleverAge\UiProcessBundle\Admin\Field\EnumField;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Translation\TranslatableMessage;

#[CoversClass(EnumField::class)]
class EnumFieldTest extends TestCase
{
public function testNew(): void
{
$dto = EnumField::new('myProperty', 'My label')->getAsDto();

self::assertSame('myProperty', $dto->getProperty());
self::assertSame('My label', $dto->getLabel());
self::assertSame('@CleverAgeUiProcess/admin/field/enum.html.twig', $dto->getTemplatePath());
}

public function testNewWithTranslatableLabel(): void
{
$label = new TranslatableMessage('my.label');

self::assertSame($label, EnumField::new('myProperty', $label)->getAsDto()->getLabel());
}

public function testNewWithoutLabel(): void
{
self::assertNull(EnumField::new('myProperty')->getAsDto()->getLabel());
}
}
44 changes: 44 additions & 0 deletions tests/Admin/Field/LogLevelFieldTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

/*
* This file is part of the CleverAge/UiProcessBundle package.
*
* Copyright (c) Clever-Age
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace CleverAge\UiProcessBundle\Tests\Admin\Field;

use CleverAge\UiProcessBundle\Admin\Field\LogLevelField;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Translation\TranslatableMessage;

#[CoversClass(LogLevelField::class)]
class LogLevelFieldTest extends TestCase
{
public function testNew(): void
{
$dto = LogLevelField::new('myProperty', 'My label')->getAsDto();

self::assertSame('myProperty', $dto->getProperty());
self::assertSame('My label', $dto->getLabel());
self::assertSame('@CleverAgeUiProcess/admin/field/log_level.html.twig', $dto->getTemplatePath());
}

public function testNewWithTranslatableLabel(): void
{
$label = new TranslatableMessage('my.label');

self::assertSame($label, LogLevelField::new('myProperty', $label)->getAsDto()->getLabel());
}

public function testNewWithoutLabel(): void
{
self::assertNull(LogLevelField::new('myProperty')->getAsDto()->getLabel());
}
}
106 changes: 106 additions & 0 deletions tests/Admin/Filter/LogProcessFilterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
<?php

declare(strict_types=1);

/*
* This file is part of the CleverAge/UiProcessBundle package.
*
* Copyright (c) Clever-Age
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace CleverAge\UiProcessBundle\Tests\Admin\Filter;

use CleverAge\UiProcessBundle\Admin\Filter\LogProcessFilter;
use CleverAge\UiProcessBundle\Entity\LogRecord;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query\Expr;
use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FilterDataDto;
use EasyCorp\Bundle\EasyAdminBundle\Form\Filter\Type\ChoiceFilterType;
use EasyCorp\Bundle\EasyAdminBundle\Form\Type\ComparisonType;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase;

#[CoversClass(LogProcessFilter::class)]
class LogProcessFilterTest extends TestCase
{
public function testNewWithChoices(): void
{
$dto = LogProcessFilter::new('Process', ['demo.a' => 'demo.a', 'demo.b' => 'demo.b'])->getAsDto();

self::assertSame(LogProcessFilter::class, $dto->getFqcn());
self::assertSame('process', $dto->getProperty());
self::assertSame('Process', $dto->getLabel());
self::assertSame(ChoiceFilterType::class, $dto->getFormType());
self::assertSame(['choices' => ['demo.a' => 'demo.a', 'demo.b' => 'demo.b']], $dto->getFormTypeOption('value_type_options'));
self::assertSame(['comparison' => ComparisonType::EQ, 'value' => null], $dto->getFormTypeOption('data'));
}

public function testNewWithExecutionIdReplacesChoices(): void
{
$dto = LogProcessFilter::new('Process', ['demo.a' => 'demo.a'], '12')->getAsDto();

self::assertSame(['choices' => [12 => '12']], $dto->getFormTypeOption('value_type_options'));
self::assertSame(['comparison' => ComparisonType::EQ, 'value' => '12'], $dto->getFormTypeOption('data'));
}

public function testNewWithNonNumericExecutionIdKeepsChoices(): void
{
$dto = LogProcessFilter::new('Process', ['demo.a' => 'demo.a'], 'demo.a')->getAsDto();

self::assertSame(['choices' => ['demo.a' => 'demo.a']], $dto->getFormTypeOption('value_type_options'));
self::assertSame(['comparison' => ComparisonType::EQ, 'value' => 'demo.a'], $dto->getFormTypeOption('data'));
}

public function testApplyWithExecutionId(): void
{
$queryBuilder = $this->createQueryBuilder();

$this->apply($queryBuilder, '12');

self::assertSame(
'SELECT entity FROM '.LogRecord::class.' entity INNER JOIN entity.processExecution pe WHERE pe.id = :id',
$queryBuilder->getDQL()
);
self::assertCount(1, $queryBuilder->getParameters());
self::assertSame('12', $queryBuilder->getParameter('id')?->getValue());
}

public function testApplyWithProcessCodes(): void
{
$queryBuilder = $this->createQueryBuilder();

$this->apply($queryBuilder, ['demo.a', 'demo.b']);

self::assertSame(
'SELECT entity FROM '.LogRecord::class.' entity INNER JOIN entity.processExecution pe WHERE pe.code IN (:codes)',
$queryBuilder->getDQL()
);
self::assertCount(1, $queryBuilder->getParameters());
self::assertSame(['demo.a', 'demo.b'], $queryBuilder->getParameter('codes')?->getValue());
}

private function createQueryBuilder(): QueryBuilder
{
$entityManager = $this->createStub(EntityManagerInterface::class);
$entityManager->method('getExpressionBuilder')->willReturn(new Expr());

return (new QueryBuilder($entityManager))->select('entity')->from(LogRecord::class, 'entity');
}

private function apply(QueryBuilder $queryBuilder, mixed $value): void
{
$filter = LogProcessFilter::new('Process', []);
$filterDataDto = FilterDataDto::new(0, $filter->getAsDto(), 'entity', ['comparison' => ComparisonType::EQ, 'value' => $value]);

/** @var EntityDto<object> $entityDto */
$entityDto = new EntityDto(LogRecord::class, new ClassMetadata(LogRecord::class));

$filter->apply($queryBuilder, $filterDataDto, null, $entityDto);
}
}
104 changes: 104 additions & 0 deletions tests/Admin/Filter/ProcessExecutionDurationFilterTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
<?php

declare(strict_types=1);

/*
* This file is part of the CleverAge/UiProcessBundle package.
*
* Copyright (c) Clever-Age
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace CleverAge\UiProcessBundle\Tests\Admin\Filter;

use CleverAge\UiProcessBundle\Admin\Filter\ProcessExecutionDurationFilter;
use CleverAge\UiProcessBundle\Entity\ProcessExecution;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto;
use EasyCorp\Bundle\EasyAdminBundle\Dto\FilterDataDto;
use EasyCorp\Bundle\EasyAdminBundle\Form\Filter\Type\NumericFilterType;
use EasyCorp\Bundle\EasyAdminBundle\Form\Type\ComparisonType;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

#[CoversClass(ProcessExecutionDurationFilter::class)]
class ProcessExecutionDurationFilterTest extends TestCase
{
public function testNew(): void
{
$dto = ProcessExecutionDurationFilter::new('duration', 'Duration')->getAsDto();

self::assertSame(ProcessExecutionDurationFilter::class, $dto->getFqcn());
self::assertSame('duration', $dto->getProperty());
self::assertSame('Duration', $dto->getLabel());
self::assertSame(NumericFilterType::class, $dto->getFormType());
self::assertSame('EasyAdminBundle', $dto->getFormTypeOption('translation_domain'));
}

#[DataProvider('provideComparisons')]
public function testApplyWithComparison(string $comparison): void
{
$queryBuilder = $this->apply(['comparison' => $comparison, 'value' => 60]);

self::assertSame(
'SELECT entity FROM '.ProcessExecution::class.' entity WHERE entity.endDate '.$comparison
.' date_add(entity.startDate, 60, \'SECOND\')',
$queryBuilder->getDQL()
);
}

/**
* @return iterable<string, array{string}>
*/
public static function provideComparisons(): iterable
{
yield 'eq' => [ComparisonType::EQ];
yield 'neq' => [ComparisonType::NEQ];
yield 'gt' => [ComparisonType::GT];
yield 'gte' => [ComparisonType::GTE];
yield 'lt' => [ComparisonType::LT];
yield 'lte' => [ComparisonType::LTE];
}

public function testApplyBetween(): void
{
$queryBuilder = $this->apply(['comparison' => ComparisonType::BETWEEN, 'value' => 10, 'value2' => 120]);

self::assertSame(
'SELECT entity FROM '.ProcessExecution::class.' entity WHERE entity.endDate BETWEEN '
.'date_add(entity.startDate, 10, \'SECOND\') and date_add(entity.startDate, 120, \'SECOND\')',
$queryBuilder->getDQL()
);
}

public function testApplyWithUnsupportedComparisonDoesNothing(): void
{
$queryBuilder = $this->apply(['comparison' => ComparisonType::CONTAINS, 'value' => 10]);

self::assertSame('SELECT entity FROM '.ProcessExecution::class.' entity', $queryBuilder->getDQL());
}

/**
* @param array{comparison: string, value: mixed, value2?: mixed} $formData
*/
private function apply(array $formData): QueryBuilder
{
$queryBuilder = (new QueryBuilder($this->createStub(EntityManagerInterface::class)))
->select('entity')
->from(ProcessExecution::class, 'entity');
$filter = ProcessExecutionDurationFilter::new('duration');
$filterDataDto = FilterDataDto::new(0, $filter->getAsDto(), 'entity', $formData);

/** @var EntityDto<object> $entityDto */
$entityDto = new EntityDto(ProcessExecution::class, new ClassMetadata(ProcessExecution::class));

$filter->apply($queryBuilder, $filterDataDto, null, $entityDto);

return $queryBuilder;
}
}
Loading
Loading