Initial commit: CloudOps infrastructure platform

This commit is contained in:
root
2026-04-09 19:58:57 +02:00
commit 1166a52f26
7762 changed files with 839452 additions and 0 deletions

View File

@@ -0,0 +1,284 @@
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Field;
use Mautic\LeadBundle\Entity\LeadField;
use Mautic\LeadBundle\Field\BackgroundService;
use Mautic\LeadBundle\Field\CustomFieldColumn;
use Mautic\LeadBundle\Field\Dispatcher\FieldColumnBackgroundJobDispatcher;
use Mautic\LeadBundle\Field\Exception\AbortColumnCreateException;
use Mautic\LeadBundle\Field\Exception\AbortColumnUpdateException;
use Mautic\LeadBundle\Field\Exception\ColumnAlreadyCreatedException;
use Mautic\LeadBundle\Field\Exception\CustomFieldLimitException;
use Mautic\LeadBundle\Field\Exception\LeadFieldWasNotFoundException;
use Mautic\LeadBundle\Field\LeadFieldDeleter;
use Mautic\LeadBundle\Field\LeadFieldSaver;
use Mautic\LeadBundle\Field\Notification\CustomFieldNotification;
use Mautic\LeadBundle\Model\FieldModel;
use PHPUnit\Framework\MockObject\MockObject;
class BackgroundServiceTest extends \PHPUnit\Framework\TestCase
{
private BackgroundService $backgroundService;
/**
* @var MockObject&FieldModel
*/
private MockObject $fieldModel;
/**
* @var MockObject&CustomFieldColumn
*/
private MockObject $customFieldColumn;
/**
* @var MockObject&LeadFieldSaver
*/
private MockObject $leadFieldSaver;
/**
* @var MockObject&LeadFieldDeleter
*/
private $leadFieldDeleter;
/**
* @var MockObject&FieldColumnBackgroundJobDispatcher
*/
private MockObject $fieldColumnBackgroundJobDispatcher;
/**
* @var MockObject&CustomFieldNotification
*/
private MockObject $customFieldNotification;
public function setUp(): void
{
$this->fieldModel = $this->createMock(FieldModel::class);
$this->customFieldColumn = $this->createMock(CustomFieldColumn::class);
$this->leadFieldSaver = $this->createMock(LeadFieldSaver::class);
$this->leadFieldDeleter = $this->createMock(LeadFieldDeleter::class);
$this->fieldColumnBackgroundJobDispatcher = $this->createMock(FieldColumnBackgroundJobDispatcher::class);
$this->customFieldNotification = $this->createMock(CustomFieldNotification::class);
$this->backgroundService = new BackgroundService(
$this->fieldModel,
$this->customFieldColumn,
$this->leadFieldSaver,
$this->leadFieldDeleter,
$this->fieldColumnBackgroundJobDispatcher,
$this->customFieldNotification
);
}
public function testNoLeadField(): void
{
$this->fieldModel->expects($this->once())
->method('getEntity')
->willReturn(null);
$this->expectException(LeadFieldWasNotFoundException::class);
$this->expectExceptionMessage('LeadField entity was not found');
$this->backgroundService->addColumn(1, 3);
}
public function testColumnAlreadyCreated(): void
{
$leadField = new LeadField();
$leadField->setColumnWasCreated();
$this->fieldModel->expects($this->once())
->method('getEntity')
->willReturn($leadField);
$userId = 3;
$this->customFieldNotification->expects($this->once())
->method('customFieldWasCreated')
->with($leadField, $userId);
$this->expectException(ColumnAlreadyCreatedException::class);
$this->expectExceptionMessage('Column was already created');
$this->backgroundService->addColumn(1, $userId);
}
public function testAbortColumnCreate(): void
{
$leadField = new LeadField();
$leadField->setColumnIsNotCreated();
$this->fieldModel->expects($this->once())
->method('getEntity')
->willReturn($leadField);
$userId = 3;
$this->fieldColumnBackgroundJobDispatcher->expects($this->once())
->method('dispatchPreAddColumnEvent')
->with($leadField)
->willThrowException(new AbortColumnCreateException('Message'));
$this->expectException(AbortColumnCreateException::class);
$this->expectExceptionMessage('Message');
$this->backgroundService->addColumn(1, $userId);
}
public function testAbortColumnUpdate(): void
{
$leadField = new LeadField();
$this->fieldModel->expects($this->once())
->method('getEntity')
->willReturn($leadField);
$userId = 3;
$this->fieldColumnBackgroundJobDispatcher->expects($this->once())
->method('dispatchPreUpdateColumnEvent')
->with($leadField)
->willThrowException(new AbortColumnUpdateException('Message'));
$this->expectException(AbortColumnUpdateException::class);
$this->expectExceptionMessage('Message');
$this->backgroundService->updateColumn(1, $userId);
}
public function testCustomFieldLimit(): void
{
$leadField = new LeadField();
$leadField->setColumnIsNotCreated();
$this->fieldModel->expects($this->once())
->method('getEntity')
->willReturn($leadField);
$this->fieldColumnBackgroundJobDispatcher->expects($this->once())
->method('dispatchPreAddColumnEvent')
->with($leadField);
$this->customFieldColumn->expects($this->once())
->method('processCreateLeadColumn')
->with($leadField, false)
->willThrowException(new CustomFieldLimitException('Limit'));
$userId = 3;
$this->customFieldNotification->expects($this->once())
->method('customFieldLimitWasHit')
->with($leadField, $userId);
$this->expectException(CustomFieldLimitException::class);
$this->expectExceptionMessage('Limit');
$this->backgroundService->addColumn(1, $userId);
}
public function testCreateColumnWithNoError(): void
{
$leadField = new LeadField();
$leadField->setColumnIsNotCreated();
$this->fieldModel->expects($this->once())
->method('getEntity')
->willReturn($leadField);
$this->fieldColumnBackgroundJobDispatcher->expects($this->once())
->method('dispatchPreAddColumnEvent')
->with($leadField);
$this->customFieldColumn->expects($this->once())
->method('processCreateLeadColumn')
->with($leadField, false);
$this->leadFieldSaver->expects($this->once())
->method('saveLeadFieldEntity')
->with($leadField, false);
$userId = 3;
$this->customFieldNotification->expects($this->once())
->method('customFieldWasCreated')
->with($leadField, $userId);
$this->backgroundService->addColumn(1, $userId);
$this->assertFalse($leadField->getColumnIsNotCreated());
}
public function testUpdateColumnWithNoError(): void
{
$leadField = new LeadField();
$this->fieldModel->expects($this->once())
->method('getEntity')
->willReturn($leadField);
$this->fieldColumnBackgroundJobDispatcher->expects($this->once())
->method('dispatchPreUpdateColumnEvent')
->with($leadField);
$this->customFieldColumn->expects($this->once())
->method('processUpdateLeadColumn')
->with($leadField);
$userId = 3;
$this->customFieldNotification->expects($this->once())
->method('customFieldWasUpdated')
->with($leadField, $userId);
$this->backgroundService->updateColumn(1, $userId);
}
public function testUpdatingLeadFieldWithNotFoundException(): void
{
$this->expectException(LeadFieldWasNotFoundException::class);
$this->fieldModel->expects($this->once())
->method('getEntity')
->willReturn(null);
$this->backgroundService->updateColumn(-1, 0);
}
public function testUpdateColumnThrowingExceptions(): void
{
$leadField = new LeadField();
$leadField->setCharLengthLimit(200);
$leadField->setId(9999);
$this->fieldModel->expects($this->once())
->method('getEntity')
->willReturn($leadField);
$this->customFieldColumn->expects($this->once())
->method('processUpdateLeadColumnLength')
->with($leadField)
->willThrowException(new \OutOfRangeException());
$this->expectException(\OutOfRangeException::class);
$this->backgroundService->updateColumn($leadField->getId(), 1);
}
public function testDeleteColumnWithNoError(): void
{
$leadField = new LeadField();
$this->fieldModel->expects($this->once())
->method('getEntity')
->willReturn($leadField);
$this->fieldColumnBackgroundJobDispatcher->expects($this->once())
->method('dispatchPreDeleteColumnEvent')
->with($leadField);
$this->customFieldColumn->expects($this->once())
->method('processDeleteLeadColumn')
->with($leadField);
$userId = 3;
$this->customFieldNotification->expects($this->once())
->method('customFieldWasDeleted')
->with($leadField, $userId);
$this->backgroundService->deleteColumn(1, $userId);
}
}

View File

@@ -0,0 +1,190 @@
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Field\Command;
use Mautic\CoreBundle\Doctrine\Helper\ColumnSchemaHelper;
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
use Mautic\LeadBundle\Entity\Lead;
use Mautic\LeadBundle\Entity\LeadField;
use Mautic\LeadBundle\Model\FieldModel;
use Mautic\LeadBundle\Model\LeadModel;
final class AnalyseCustomFieldCommandFunctionalTest extends MauticMysqlTestCase
{
protected $useCleanupRollback = false;
public function testAnalyseWhenNoCustomFieldPresent(): void
{
$commandTester = $this->testSymfonyCommand('mautic:fields:analyse');
$this->assertStringContainsString('No custom field(s) to analyse!!!', $commandTester->getDisplay());
}
public function testAnalyseCustomField(): void
{
$fields = [
'analyse_field_one' => [
'label' => 'Field one',
'alias' => 'analyse_field_one',
'type' => 'text',
'limit' => 191,
'value' => $this->getText(180),
'expected' => 191,
],
'analyse_field_two' => [
'label' => 'Field two',
'alias' => 'analyse_field_two',
'type' => 'text',
'limit' => 50,
'value' => $field2Val = $this->getText(10),
'expected' => strlen($field2Val) * 2,
],
'analyse_field_country' => [
'label' => 'Field country',
'alias' => 'analyse_field_country',
'type' => 'country',
'limit' => 255,
'value' => '',
'expected' => 191,
],
'analyse_field_text_greater_than_191' => [
'label' => 'Text greater than 191',
'alias' => 'analyse_field_text_greater_than_191',
'type' => 'text',
'limit' => 255,
'value' => $this->getText(240),
'expected' => 255,
],
'range' => [
'label' => 'Range',
'alias' => 'range',
'type' => 'text',
'limit' => 64,
'value' => '',
'expected' => 64,
],
];
foreach ($fields as $field) {
$this->createCustomField($field);
}
$this->createLead($fields);
// Add long text.
$extraField = [
'label' => 'Field three',
'alias' => 'analyse_field_three',
'type' => 'html',
];
$this->createCustomField($extraField);
$output = $this->testSymfonyCommand('mautic:fields:analyse');
foreach ($fields as $alias => $field) {
$this->assertStringContainsString($alias, $output->getDisplay());
$this->assertStringContainsString($field['label'], $output->getDisplay());
$this->assertStringContainsString((string) $field['limit'], $output->getDisplay());
$this->assertStringContainsString((string) $field['expected'], $output->getDisplay());
}
$this->assertStringNotContainsString($extraField['label'], $output->getDisplay());
$output = $this->testSymfonyCommand('mautic:fields:analyse', ['--display-table' => true]);
foreach ($fields as $alias => $field) {
$this->assertStringContainsString($alias, $output->getDisplay());
$this->assertStringContainsString($field['label'], $output->getDisplay());
$this->assertStringContainsString((string) $field['limit'], $output->getDisplay());
$this->assertStringContainsString((string) $field['expected'], $output->getDisplay());
}
}
public function testCustomFieldWhenColumnIsNotExistsInLeadsSchema(): void
{
// Create a field and add it to the lead object.
$field = new LeadField();
$field->setAlias('unknown');
$field->setLabel('Unknown');
/** @var FieldModel $fieldModel */
$fieldModel = $this->getContainer()->get('mautic.lead.model.field');
$fieldModel->saveEntity($field);
/** @var ColumnSchemaHelper $columnSchemaHelper */
$columnSchemaHelper = $this->getContainer()->get('mautic.schema.helper.column');
$columnSchemaHelper->setName('leads')->dropColumn($field->getAlias())->executeChanges();
$output = $this->testSymfonyCommand('mautic:fields:analyse');
$this->assertStringContainsString('No custom field(s) to analyse!!!', $output->getDisplay());
$fieldModel->deleteEntity($field);
}
/**
* @param array<string, mixed> $fieldDetails
*/
private function createCustomField(array $fieldDetails): void
{
// Create a field and add it to the lead object.
$field = new LeadField();
$field->setLabel($fieldDetails['label']);
$field->setType($fieldDetails['type']);
$field->setObject('lead');
$field->setGroup('core');
$field->setAlias($fieldDetails['alias']);
if (!empty($fieldDetails['limit'])) {
$field->setCharLengthLimit($fieldDetails['limit']);
}
/** @var FieldModel $fieldModel */
$fieldModel = $this->getContainer()->get('mautic.lead.model.field');
$fieldModel->saveEntity($field);
}
/**
* @param array<string, mixed> $fieldDetails
*/
private function createLead(array $fieldDetails): void
{
$lead = new Lead();
$lead->setFirstname('Test lead');
$lead->setEmail('lead@test.in');
foreach ($fieldDetails as $alias => $fieldDetail) {
if (empty($fieldDetail['value'])) {
continue;
}
$lead->addUpdatedField($alias, $fieldDetail['value']);
}
/** @var LeadModel $leadModel */
$leadModel = $this->getContainer()->get('mautic.lead.model.lead');
$leadModel->saveEntity($lead);
}
private function getText(int $chars = 191): string
{
$dummyText = 'Aenean consectetur efficitur congue Aliquam faucibus tempor nisi ut dignissim Ut non metus enim Maecenas mattis quam a hendrerit condimentum elit leo bibendum';
$words = explode(' ', $dummyText);
$text = [];
$size = 0;
while ($size < $chars) {
$word = ($size ? ' ' : '').$words[array_rand($words)];
$text[] = $word;
$size += strlen($word);
}
array_pop($text);
if (isset($text[count($text) - 1])) {
$text[count($text) - 1] .= '.';
}
return implode('', $text);
}
}

View File

@@ -0,0 +1,68 @@
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Field\Command;
use Mautic\LeadBundle\Entity\LeadFieldRepository;
use Mautic\LeadBundle\Field\BackgroundService;
use Mautic\LeadBundle\Field\Command\DeleteCustomFieldCommand;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Tester\CommandTester;
use Symfony\Contracts\Translation\TranslatorInterface;
final class DeleteCustomFieldCommandTest extends TestCase
{
/**
* @var MockObject&BackgroundService
*/
private MockObject $backgroundServiceMock;
/**
* @var MockObject&TranslatorInterface
*/
private MockObject $translatorInterfaceMock;
/**
* @var MockObject&LeadFieldRepository
*/
private MockObject $leadFieldRepository;
private DeleteCustomFieldCommand $deleteCustomFieldCommand;
protected function setUp(): void
{
$this->backgroundServiceMock = $this->createMock(BackgroundService::class);
$this->translatorInterfaceMock = $this->createMock(TranslatorInterface::class);
$this->leadFieldRepository = $this->createMock(LeadFieldRepository::class);
$this->deleteCustomFieldCommand = new DeleteCustomFieldCommand(
$this->backgroundServiceMock,
$this->translatorInterfaceMock,
$this->leadFieldRepository,
);
}
public function testExecute(): void
{
$this->backgroundServiceMock
->expects($this->once())
->method('deleteColumn')
->with(42, 0);
$this->translatorInterfaceMock
->expects($this->once())
->method('trans')
->with('mautic.lead.field.column_was_deleted')
->willReturn('Column was deleted');
$commandTester = new CommandTester($this->deleteCustomFieldCommand);
$commandTester->execute([
// pass arguments to the command
'--id' => '42',
'--user' => '0',
]);
// the output of the command in the console
$output = $commandTester->getDisplay();
$this->assertStringContainsString('Column was deleted', $output);
}
}

View File

@@ -0,0 +1,121 @@
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Field\Command;
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
use Mautic\LeadBundle\Entity\LeadField;
use Mautic\LeadBundle\Model\FieldModel;
use Symfony\Component\Console\Command\Command;
final class ModifyCustomFieldCommandFunctionalTest extends MauticMysqlTestCase
{
protected $useCleanupRollback = false;
/**
* @var string[]
*/
private array $csvFiles = [];
protected function beforeTearDown(): void
{
foreach ($this->csvFiles as $file) {
if (file_exists($file)) {
unlink($file);
}
}
}
public function testUpdateCustomFieldsRunsIntoException(): void
{
$commandTester = $this->testSymfonyCommand('mautic:fields:modify', [
'csv-path' => dirname(__FILE__).'/random.csv',
]);
$this->assertSame(Command::FAILURE, $commandTester->getStatusCode());
$this->assertStringContainsString('Could not open file', $commandTester->getDisplay());
}
public function testUpdateCustomFields(): void
{
$csvRows = [
'field_text_one' => ['label' => 'Test text one', 'alias' => 'field_text_one', 'len' => 191, 'newLen' => 100],
'field_text_two' => ['label' => 'Test text two', 'alias' => 'field_text_two', 'len' => 100, 'newLen' => 100],
'field_text_three' => ['label' => 'Test text three', 'alias' => 'field_text_three', 'len' => 100, 'newLen' => 1000],
];
$file = $this->generateSmallCSV($csvRows);
$this->createCustomFields($csvRows);
$output = $this->testSymfonyCommand('mautic:fields:modify', ['csv-path' => $file])->getDisplay();
$this->assertStringContainsString('Skipping "Test text three", the suggested length must be between 1 and 191.', $output);
$this->assertStringContainsString('1 Field(s) updated successfully.', $output);
/** @var FieldModel $fieldModel */
$fieldModel = $this->getContainer()->get('mautic.lead.model.field');
$field = $fieldModel->getEntityByAlias('field_text_one');
$this->assertEquals($field->getCharLengthLimit(), $csvRows['field_text_one']['newLen']);
}
public function testUpdateNoFieldAsItHasSameSizeAsSuggested(): void
{
$csvRows = [
['label' => 'Test text four', 'alias' => 'field_text_four', 'len' => 100, 'newLen' => 100],
];
$file = $this->generateSmallCSV($csvRows);
$this->createCustomFields($csvRows);
$output = $this->testSymfonyCommand('mautic:fields:modify', ['csv-path' => $file])->getDisplay();
$this->assertStringContainsString('No custom field(s) to update!!!', $output);
}
/**
* @param mixed[] $rows
*/
private function createCustomFields(array $rows): void
{
$fields = [];
foreach ($rows as $fieldDetails) {
$field = new LeadField();
$field->setType('text');
$field->setObject('lead');
$field->setGroup('core');
$field->setLabel($fieldDetails['label']);
$field->setAlias($fieldDetails['alias']);
$field->setCharLengthLimit($fieldDetails['len']);
$fields[] = $field;
}
/** @var FieldModel $fieldModel */
$fieldModel = $this->getContainer()->get('mautic.lead.model.field');
$fieldModel->saveEntities($fields);
$fieldModel->getRepository()->detachEntities($fields);
}
/**
* @param mixed[] $rows
*/
private function generateSmallCSV(array $rows): string
{
$tmpFile = tempnam(sys_get_temp_dir(), 'mautic_update_fields_').'.csv';
$file = fopen($tmpFile, 'wb');
$csvHeader = ['Custom Field Name', 'Custom Field Alias', 'Current Size', 'Suggested max size'];
fputcsv($file, $csvHeader, ',', '"', '\\');
foreach ($rows as $line) {
fputcsv($file, $line, ',', '"', '\\');
}
fclose($file);
$this->csvFiles[] = $tmpFile;
return $tmpFile;
}
}

View File

@@ -0,0 +1,594 @@
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Field;
use Mautic\CoreBundle\Doctrine\Helper\ColumnSchemaHelper;
use Mautic\LeadBundle\Entity\LeadField;
use Mautic\LeadBundle\Field\CustomFieldColumn;
use Mautic\LeadBundle\Field\CustomFieldIndex;
use Mautic\LeadBundle\Field\Dispatcher\FieldColumnDispatcher;
use Mautic\LeadBundle\Field\Exception\AbortColumnCreateException;
use Mautic\LeadBundle\Field\Exception\AbortColumnUpdateException;
use Mautic\LeadBundle\Field\Exception\CustomFieldLimitException;
use Mautic\LeadBundle\Field\LeadFieldSaver;
use Mautic\LeadBundle\Field\SchemaDefinition;
use Monolog\Logger;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Contracts\Translation\TranslatorInterface;
class CustomFieldColumnTest extends \PHPUnit\Framework\TestCase
{
/**
* @var MockObject|ColumnSchemaHelper
*/
private MockObject $columnSchemaHelper;
/**
* @var MockObject|SchemaDefinition
*/
private MockObject $schemaDefinition;
/**
* @var MockObject|Logger
*/
private MockObject $logger;
/**
* @var MockObject|LeadFieldSaver
*/
private MockObject $leadFieldSaver;
/**
* @var MockObject|CustomFieldIndex
*/
private MockObject $customFieldIndex;
/**
* @var MockObject|FieldColumnDispatcher
*/
private MockObject $fieldColumnDispatcher;
/**
* @var MockObject|TranslatorInterface
*/
private MockObject $translator;
private CustomFieldColumn $customFieldColumn;
protected function setUp(): void
{
parent::setUp();
$this->columnSchemaHelper = $this->createMock(ColumnSchemaHelper::class);
$this->schemaDefinition = $this->createMock(SchemaDefinition::class);
$this->logger = $this->createMock(Logger::class);
$this->leadFieldSaver = $this->createMock(LeadFieldSaver::class);
$this->customFieldIndex = $this->createMock(CustomFieldIndex::class);
$this->fieldColumnDispatcher = $this->createMock(FieldColumnDispatcher::class);
$this->translator = $this->createMock(TranslatorInterface::class);
$this->customFieldColumn = new CustomFieldColumn(
$this->columnSchemaHelper,
$this->schemaDefinition,
$this->logger,
$this->leadFieldSaver,
$this->customFieldIndex,
$this->fieldColumnDispatcher,
$this->translator
);
}
public function testColumnExists(): void
{
$leadField = new LeadField();
$this->columnSchemaHelper->expects($this->exactly(2))
->method('setName')
->willReturn($this->columnSchemaHelper);
$this->columnSchemaHelper->expects($this->exactly(2))
->method('checkColumnExists')
->willReturn(true);
$this->fieldColumnDispatcher->expects($this->never())
->method('dispatchPreAddColumnEvent');
$this->columnSchemaHelper->expects($this->never())
->method('addColumn');
$this->customFieldColumn->createLeadColumn($leadField);
$this->customFieldColumn->processCreateLeadColumn($leadField);
}
public function testAbortColumnCreation(): void
{
$this->columnSchemaHelper->expects($this->once())
->method('setName')
->willReturn($this->columnSchemaHelper);
$this->columnSchemaHelper->expects($this->once())
->method('checkColumnExists')
->willReturn(false);
$this->fieldColumnDispatcher->expects($this->once())
->method('dispatchPreAddColumnEvent')
->willThrowException(new AbortColumnCreateException('Message'));
$this->columnSchemaHelper->expects($this->never())
->method('addColumn');
$this->expectException(AbortColumnCreateException::class);
$this->expectExceptionMessage('Message');
$this->customFieldColumn->createLeadColumn(new LeadField());
}
public function testCustomFieldLimit(): void
{
$leadField = new LeadField();
$leadField->setAlias('zip');
$leadField->setType('text');
$this->columnSchemaHelper->expects($this->once())
->method('setName')
->willReturn($this->columnSchemaHelper);
$this->columnSchemaHelper->expects($this->once())
->method('checkColumnExists')
->willReturn(false);
$this->schemaDefinition->expects($this->once())
->method('getSchemaDefinitionNonStatic')
->willReturn([]);
$this->columnSchemaHelper->expects($this->once())
->method('addColumn');
$dbalException = new class('message', 1118) extends \Exception implements \Doctrine\DBAL\Driver\Exception {
public function getSQLState(): string
{
return 'some SQL state';
}
};
$driverException = new \Doctrine\DBAL\Exception\DriverException($dbalException, null);
$this->columnSchemaHelper->expects($this->once())
->method('executeChanges')
->willThrowException($driverException);
$this->expectException(CustomFieldLimitException::class);
$this->expectExceptionMessage('mautic.lead.field.max_column_error');
$this->customFieldColumn->processCreateLeadColumn($leadField);
}
public function testNoErrorWithAddColumnIndex(): void
{
$leadField = new LeadField();
$leadField->setAlias('zip');
$leadField->setType('text');
$leadField->setIsIndex(true);
$this->columnSchemaHelper->expects($this->once())
->method('setName')
->willReturn($this->columnSchemaHelper);
$this->columnSchemaHelper->expects($this->once())
->method('checkColumnExists')
->willReturn(false);
$this->schemaDefinition->expects($this->once())
->method('getSchemaDefinitionNonStatic')
->willReturn(['type' => 'string']);
$this->columnSchemaHelper->expects($this->once())
->method('addColumn');
$this->columnSchemaHelper->expects($this->once())
->method('executeChanges');
$this->leadFieldSaver->expects($this->once())
->method('saveLeadFieldEntity')
->with($leadField, true);
$this->customFieldIndex->expects($this->once())
->method('addIndexOnColumn')
->with($leadField);
$this->customFieldColumn->processCreateLeadColumn($leadField);
}
public function testNoErrorWithAddColumnIndexForUniqueIdentifier(): void
{
$columnSchemaHelper = $this->createMock(ColumnSchemaHelper::class);
$schemaDefinition = $this->createMock(SchemaDefinition::class);
$logger = $this->createMock(Logger::class);
$leadFieldSaver = $this->createMock(LeadFieldSaver::class);
$customFieldIndex = $this->createMock(CustomFieldIndex::class);
$fieldColumnDispatcher = $this->createMock(FieldColumnDispatcher::class);
$translator = $this->createMock(TranslatorInterface::class);
$customFieldColumn = new CustomFieldColumn($columnSchemaHelper, $schemaDefinition, $logger, $leadFieldSaver, $customFieldIndex, $fieldColumnDispatcher, $translator);
$columnSchemaHelper->expects($this->once())
->method('setName')
->willReturn($columnSchemaHelper);
$columnSchemaHelper->expects($this->once())
->method('checkColumnExists')
->willReturn(false);
$leadField = new LeadField();
$leadField->setAlias('text');
$leadField->setIsUniqueIdentifier(true);
$schemaDefinition->expects($this->once())
->method('getSchemaDefinitionNonStatic')
->willReturn(['type' => 'string']);
$columnSchemaHelper->expects($this->once())
->method('addColumn');
$columnSchemaHelper->expects($this->once())
->method('executeChanges');
$leadFieldSaver->expects($this->once())
->method('saveLeadFieldEntity')
->with($leadField, true);
$customFieldIndex->expects($this->once())
->method('addIndexOnColumn')
->with($leadField);
$customFieldColumn->processCreateLeadColumn($leadField);
}
public function testNoErrorWithAddColumnWithoutIndexOrUniqueIdentifier(): void
{
$columnSchemaHelper = $this->createMock(ColumnSchemaHelper::class);
$schemaDefinition = $this->createMock(SchemaDefinition::class);
$logger = $this->createMock(Logger::class);
$leadFieldSaver = $this->createMock(LeadFieldSaver::class);
$customFieldIndex = $this->createMock(CustomFieldIndex::class);
$fieldColumnDispatcher = $this->createMock(FieldColumnDispatcher::class);
$translator = $this->createMock(TranslatorInterface::class);
$customFieldColumn = new CustomFieldColumn($columnSchemaHelper, $schemaDefinition, $logger, $leadFieldSaver, $customFieldIndex, $fieldColumnDispatcher, $translator);
$columnSchemaHelper->expects($this->once())
->method('setName')
->willReturn($columnSchemaHelper);
$columnSchemaHelper->expects($this->once())
->method('checkColumnExists')
->willReturn(false);
$leadField = new LeadField();
$leadField->setAlias('text');
$schemaDefinition->expects($this->once())
->method('getSchemaDefinitionNonStatic')
->willReturn(['type' => 'string']);
$columnSchemaHelper->expects($this->once())
->method('addColumn');
$columnSchemaHelper->expects($this->once())
->method('executeChanges');
$leadFieldSaver->expects($this->once())
->method('saveLeadFieldEntity')
->with($leadField, true);
$customFieldIndex->expects($this->never())
->method('addIndexOnColumn');
$customFieldColumn->processCreateLeadColumn($leadField);
}
public function testNoErrorWithUpdateAddColumnIndex(): void
{
$columnSchemaHelper = $this->createMock(ColumnSchemaHelper::class);
$schemaDefinition = $this->createMock(SchemaDefinition::class);
$logger = $this->createMock(Logger::class);
$leadFieldSaver = $this->createMock(LeadFieldSaver::class);
$customFieldIndex = $this->createMock(CustomFieldIndex::class);
$fieldColumnDispatcher = $this->createMock(FieldColumnDispatcher::class);
$translator = $this->createMock(TranslatorInterface::class);
$customFieldColumn = new CustomFieldColumn($columnSchemaHelper, $schemaDefinition, $logger, $leadFieldSaver, $customFieldIndex, $fieldColumnDispatcher, $translator);
$leadField = new LeadField();
$leadField->setIsIndex(true);
$customFieldIndex->expects($this->once())
->method('hasIndex')
->with($leadField)
->willReturn(false);
$customFieldIndex->expects($this->once())
->method('addIndexOnColumn')
->with($leadField);
$customFieldColumn->processUpdateLeadColumn($leadField);
}
public function testNoErrorWithUpdateRemoveColumnIndex(): void
{
$columnSchemaHelper = $this->createMock(ColumnSchemaHelper::class);
$schemaDefinition = $this->createMock(SchemaDefinition::class);
$logger = $this->createMock(Logger::class);
$leadFieldSaver = $this->createMock(LeadFieldSaver::class);
$customFieldIndex = $this->createMock(CustomFieldIndex::class);
$fieldColumnDispatcher = $this->createMock(FieldColumnDispatcher::class);
$translator = $this->createMock(TranslatorInterface::class);
$customFieldColumn = new CustomFieldColumn($columnSchemaHelper, $schemaDefinition, $logger, $leadFieldSaver, $customFieldIndex, $fieldColumnDispatcher, $translator);
$leadField = new LeadField();
$leadField->setIsIndex(false);
$customFieldIndex->expects($this->once())
->method('hasIndex')
->with($leadField)
->willReturn(true);
$customFieldIndex->expects($this->once())
->method('dropIndexOnColumn')
->with($leadField);
$customFieldColumn->processUpdateLeadColumn($leadField);
}
public function testNoErrorNoColumnIndex(): void
{
$leadField = new LeadField();
$leadField->setAlias('zip');
$leadField->setType('text');
$this->columnSchemaHelper->expects($this->once())
->method('setName')
->willReturn($this->columnSchemaHelper);
$this->columnSchemaHelper->expects($this->once())
->method('checkColumnExists')
->willReturn(false);
$this->schemaDefinition->expects($this->once())
->method('getSchemaDefinitionNonStatic')
->willReturn(['type' => 'date']);
$this->columnSchemaHelper->expects($this->once())
->method('addColumn');
$this->columnSchemaHelper->expects($this->once())
->method('executeChanges');
$this->leadFieldSaver->expects($this->once())
->method('saveLeadFieldEntity')
->with($leadField, true);
$this->customFieldIndex->expects($this->never())
->method('addIndexOnColumn');
$this->customFieldColumn->processCreateLeadColumn($leadField);
}
public function testUniqueIdentifierColumnCreation(): void
{
$leadField = new LeadField();
// Creating the entity from a form will hydrate this with 0/1 instead of a true/false
// Testing that the getter now appropriately returns a bool for the type hinted getSchemaDefinitionNonStatic
$leadField->setIsUniqueIdentifier(1);
$leadField->setAlias('zip');
$leadField->setType('text');
$this->columnSchemaHelper->expects($this->once())
->method('setName')
->willReturn($this->columnSchemaHelper);
$this->columnSchemaHelper->expects($this->once())
->method('checkColumnExists')
->willReturn(false);
$this->schemaDefinition->expects($this->once())
->method('getSchemaDefinitionNonStatic')
->willReturn(['type' => 'string']);
$this->columnSchemaHelper->expects($this->once())
->method('addColumn');
$this->columnSchemaHelper->expects($this->once())
->method('executeChanges');
$this->leadFieldSaver->expects($this->once())
->method('saveLeadFieldEntity')
->with($leadField, true);
$this->customFieldIndex->expects($this->once())
->method('addIndexOnColumn')
->with($leadField);
$this->customFieldColumn->processCreateLeadColumn($leadField);
}
public function testDeleteLeadColumnInBacground(): void
{
$columnSchemaHelper = $this->createMock(ColumnSchemaHelper::class);
$schemaDefinition = $this->createMock(SchemaDefinition::class);
$logger = $this->createMock(Logger::class);
$leadFieldSaver = $this->createMock(LeadFieldSaver::class);
$customFieldIndex = $this->createMock(CustomFieldIndex::class);
$fieldColumnDispatcher = $this->createMock(FieldColumnDispatcher::class);
$translator = $this->createMock(TranslatorInterface::class);
$customFieldColumn = new CustomFieldColumn($columnSchemaHelper, $schemaDefinition, $logger, $leadFieldSaver, $customFieldIndex, $fieldColumnDispatcher, $translator);
$leadField = new LeadField();
$leadField->setId(42);
$leadField->setObject('lead');
$fieldColumnDispatcher->expects($this->once())
->method('dispatchPreDeleteColumnEvent')
->with($leadField)
->willThrowException(new AbortColumnUpdateException());
$columnSchemaHelper->expects($this->never())
->method('dropColumn');
$customFieldColumn->deleteLeadColumn($leadField);
}
public function testDeleteLeadColumnNow(): void
{
$columnSchemaHelper = $this->createMock(ColumnSchemaHelper::class);
$schemaDefinition = $this->createMock(SchemaDefinition::class);
$logger = $this->createMock(Logger::class);
$leadFieldSaver = $this->createMock(LeadFieldSaver::class);
$customFieldIndex = $this->createMock(CustomFieldIndex::class);
$fieldColumnDispatcher = $this->createMock(FieldColumnDispatcher::class);
$translator = $this->createMock(TranslatorInterface::class);
$customFieldColumn = new CustomFieldColumn($columnSchemaHelper, $schemaDefinition, $logger, $leadFieldSaver, $customFieldIndex, $fieldColumnDispatcher, $translator);
$leadField = new LeadField();
$leadField->setId(42);
$leadField->setObject('lead');
$leadField->setAlias('IamAlias');
$fieldColumnDispatcher->expects($this->once())
->method('dispatchPreDeleteColumnEvent')
->with($leadField);
$columnSchemaHelper->expects($this->once())
->method('setName')
->with('leads')
->willReturnSelf();
$matcher = $this->exactly(2);
$columnSchemaHelper->expects($matcher)
->method('dropColumn')->willReturnCallback(function (...$parameters) use ($matcher, $columnSchemaHelper) {
if (1 === $matcher->numberOfInvocations()) {
$this->assertSame('IamAlias', $parameters[0]);
}
if (2 === $matcher->numberOfInvocations()) {
$this->assertSame('leads', $parameters[0]);
}
return $columnSchemaHelper;
});
$columnSchemaHelper->expects($this->once())
->method('executeChanges');
$customFieldColumn->deleteLeadColumn($leadField);
}
public function testUpdateLeadColumnInBackground(): void
{
$columnSchemaHelper = $this->createMock(ColumnSchemaHelper::class);
$schemaDefinition = $this->createMock(SchemaDefinition::class);
$logger = $this->createMock(Logger::class);
$leadFieldSaver = $this->createMock(LeadFieldSaver::class);
$customFieldIndex = $this->createMock(CustomFieldIndex::class);
$fieldColumnDispatcher = $this->createMock(FieldColumnDispatcher::class);
$translator = $this->createMock(TranslatorInterface::class);
$customFieldColumn = new CustomFieldColumn($columnSchemaHelper, $schemaDefinition, $logger, $leadFieldSaver, $customFieldIndex, $fieldColumnDispatcher, $translator);
$leadField = new LeadField();
$leadField->setId(42);
$leadField->setObject('lead');
$leadField->setAlias('IamAlias');
$fieldColumnDispatcher->expects($this->once())
->method('dispatchPreUpdateColumnEvent')
->with($leadField)
->willThrowException(new AbortColumnUpdateException());
$columnSchemaHelper->expects($this->never())
->method('updateColumnLength');
$customFieldColumn->updateLeadColumn($leadField);
}
#[DataProvider('provideColumnLength')]
public function testUpdateLeadColumnNow(?int $length): void
{
$columnSchemaHelper = $this->createMock(ColumnSchemaHelper::class);
$schemaDefinition = $this->createMock(SchemaDefinition::class);
$logger = $this->createMock(Logger::class);
$leadFieldSaver = $this->createMock(LeadFieldSaver::class);
$customFieldIndex = $this->createMock(CustomFieldIndex::class);
$fieldColumnDispatcher = $this->createMock(FieldColumnDispatcher::class);
$translator = $this->createMock(TranslatorInterface::class);
$customFieldColumn = new CustomFieldColumn($columnSchemaHelper, $schemaDefinition, $logger, $leadFieldSaver, $customFieldIndex, $fieldColumnDispatcher, $translator);
$leadField = new LeadField();
$leadField->setId(42);
$leadField->setObject('lead');
$leadField->setAlias('IamAlias');
$leadField->setCharLengthLimit($length);
$fieldColumnDispatcher->expects($this->once())
->method('dispatchPreUpdateColumnEvent')
->with($leadField);
$columnSchemaHelper->expects($this->once())
->method('setName')
->with('leads')
->willReturn($columnSchemaHelper);
$columnSchemaHelper->expects($this->once())
->method('updateColumnLength')
->with('IamAlias', $length)
->willReturn($columnSchemaHelper);
$customFieldColumn->updateLeadColumn($leadField);
}
#[DataProvider('provideColumnLength')]
public function testProcessUpdateLeadColumnLength(?int $length): void
{
$columnSchemaHelper = $this->createMock(ColumnSchemaHelper::class);
$schemaDefinition = $this->createMock(SchemaDefinition::class);
$logger = $this->createMock(Logger::class);
$leadFieldSaver = $this->createMock(LeadFieldSaver::class);
$customFieldIndex = $this->createMock(CustomFieldIndex::class);
$fieldColumnDispatcher = $this->createMock(FieldColumnDispatcher::class);
$translator = $this->createMock(TranslatorInterface::class);
$customFieldColumn = new CustomFieldColumn($columnSchemaHelper, $schemaDefinition, $logger, $leadFieldSaver, $customFieldIndex, $fieldColumnDispatcher, $translator);
$leadField = new LeadField();
$leadField->setId(42);
$leadField->setObject('lead');
$leadField->setAlias('IamAlias');
$leadField->setCharLengthLimit($length);
$columnSchemaHelper->expects($this->once())
->method('setName')
->with('leads')
->willReturn($columnSchemaHelper);
$columnSchemaHelper->expects($this->once())
->method('updateColumnLength')
->with('IamAlias', $length)
->willReturn($columnSchemaHelper);
$columnSchemaHelper->expects($this->once())
->method('executeChanges');
$customFieldColumn->processUpdateLeadColumnLength($leadField);
}
public static function provideColumnLength(): \Generator
{
yield 'null' => [null];
yield '100' => [100];
}
}

View File

@@ -0,0 +1,65 @@
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Field;
use Mautic\CoreBundle\Doctrine\Helper\IndexSchemaHelper;
use Mautic\LeadBundle\Entity\LeadField;
use Mautic\LeadBundle\Field\CustomFieldIndex;
use Mautic\LeadBundle\Field\FieldsWithUniqueIdentifier;
use Monolog\Logger;
use PHPUnit\Framework\MockObject\MockObject;
final class CustomFieldIndexTest extends \PHPUnit\Framework\TestCase
{
private MockObject&IndexSchemaHelper $indexSchemaHelperMock;
private MockObject&Logger $loggerMock;
private MockObject&FieldsWithUniqueIdentifier $fieldsWithUniqueIdentifierMock;
private MockObject&LeadField $leadFieldMock;
private CustomFieldIndex $customFieldIndex;
protected function setUp(): void
{
$this->indexSchemaHelperMock = $this->createMock(IndexSchemaHelper::class);
$this->loggerMock = $this->createMock(Logger::class);
$this->fieldsWithUniqueIdentifierMock = $this->createMock(FieldsWithUniqueIdentifier::class);
$this->customFieldIndex = new CustomFieldIndex($this->indexSchemaHelperMock, $this->loggerMock, $this->fieldsWithUniqueIdentifierMock);
$this->leadFieldMock = $this->createMock(LeadField::class);
}
/**
* Test getting unique identifier if object is lead or company.
*/
#[\PHPUnit\Framework\Attributes\DataProvider('getHasMatchingUniqueIdentifierIndexProvider')]
public function testHasMatchingUniqueIdentifierIndex(string $object, string $field, string $fieldKey): void
{
$this->leadFieldMock->expects($this->once())
->method('getObject')
->willReturn($object);
$this->fieldsWithUniqueIdentifierMock->expects($this->once())
->method('getLiveFields')
->with(['object' => $object])
->willReturn([$fieldKey => $field]);
$this->indexSchemaHelperMock->expects($this->once())
->method('hasMatchingUniqueIdentifierIndex')
->with($this->leadFieldMock, [$fieldKey])
->willReturn(true);
$this->customFieldIndex->hasMatchingUniqueIdentifierIndex($this->leadFieldMock);
}
/**
* Provides data for testHasMatchingUniqueIdentifierIndex.
*
* @return iterable<string, string[]>
*/
public static function getHasMatchingUniqueIdentifierIndexProvider(): iterable
{
yield 'Lead object' => ['lead', 'email', 'email_key'];
yield 'Company object' => ['company', 'company_email', 'company_email_key'];
}
}

View File

@@ -0,0 +1,42 @@
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Field\DTO;
use Mautic\LeadBundle\Entity\LeadField;
use Mautic\LeadBundle\Exception\InvalidObjectTypeException;
use Mautic\LeadBundle\Field\DTO\CustomFieldObject;
class CustomFieldObjectTest extends \PHPUnit\Framework\TestCase
{
public function testLeadObject(): void
{
$leadField = new LeadField();
$customFieldObject = new CustomFieldObject($leadField);
$this->assertSame('leads', $customFieldObject->getObject());
}
public function testCompanyObject(): void
{
$leadField = new LeadField();
$leadField->setObject('company');
$customFieldObject = new CustomFieldObject($leadField);
$this->assertSame('companies', $customFieldObject->getObject());
}
public function testInvalidObject(): void
{
$leadField = new LeadField();
$leadField->setObject('xxx');
$this->expectException(InvalidObjectTypeException::class);
$this->expectExceptionMessage('xxx has no associated object');
new CustomFieldObject($leadField);
}
}

View File

@@ -0,0 +1,167 @@
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Field\Dispatcher;
use Mautic\LeadBundle\Entity\LeadField;
use Mautic\LeadBundle\Exception\NoListenerException;
use Mautic\LeadBundle\Field\Dispatcher\FieldColumnBackgroundJobDispatcher;
use Mautic\LeadBundle\Field\Event\AddColumnBackgroundEvent;
use Mautic\LeadBundle\Field\Event\DeleteColumnBackgroundEvent;
use Mautic\LeadBundle\Field\Event\UpdateColumnBackgroundEvent;
use Mautic\LeadBundle\Field\Exception\AbortColumnCreateException;
use Mautic\LeadBundle\Field\Exception\AbortColumnUpdateException;
use Mautic\LeadBundle\LeadEvents;
use PHPUnit\Framework\MockObject\MockObject;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class FieldColumnBackgroundJobDispatcherTest extends \PHPUnit\Framework\TestCase
{
/**
* @var MockObject&EventDispatcherInterface
*/
private MockObject $dispatcher;
protected function setUp(): void
{
$this->dispatcher = $this->createMock(EventDispatcherInterface::class);
parent::setUp();
}
public function testNoListener(): void
{
$this->dispatcher->expects($this->once())->method('hasListeners')->willReturn(false);
$this->dispatcher->expects($this->never())->method('dispatch');
$fieldColumnBackgroundJobDispatcher = new FieldColumnBackgroundJobDispatcher($this->dispatcher);
$this->expectException(NoListenerException::class);
$this->expectExceptionMessage('There is no Listener for this event');
$fieldColumnBackgroundJobDispatcher->dispatchPreAddColumnEvent(new LeadField());
}
public function testNoListenerUpdate(): void
{
$this->dispatcher->expects($this->once())->method('hasListeners')->willReturn(false);
$this->dispatcher->expects($this->never())->method('dispatch');
$fieldColumnBackgroundJobDispatcher = new FieldColumnBackgroundJobDispatcher($this->dispatcher);
$this->expectException(NoListenerException::class);
$this->expectExceptionMessage('There is no Listener for this event');
$fieldColumnBackgroundJobDispatcher->dispatchPreUpdateColumnEvent(new LeadField());
}
public function testNoListenerDelete(): void
{
$this->dispatcher->expects($this->once())->method('hasListeners')->willReturn(false);
$this->dispatcher->expects($this->never())->method('dispatch');
$fieldColumnBackgroundJobDispatcher = new FieldColumnBackgroundJobDispatcher($this->dispatcher);
$this->expectException(NoListenerException::class);
$this->expectExceptionMessage('There is no Listener for this event');
$fieldColumnBackgroundJobDispatcher->dispatchPreDeleteColumnEvent(new LeadField());
}
public function testNormalProcess(): void
{
$this->dispatcher->expects($this->once())->method('hasListeners')->willReturn(true);
$this->dispatcher->expects($this->once())->method('dispatch')->with(
$this->isInstanceOf(AddColumnBackgroundEvent::class),
LeadEvents::LEAD_FIELD_PRE_ADD_COLUMN_BACKGROUND_JOB,
);
$fieldColumnBackgroundJobDispatcher = new FieldColumnBackgroundJobDispatcher($this->dispatcher);
$fieldColumnBackgroundJobDispatcher->dispatchPreAddColumnEvent(new LeadField());
}
public function testNormalProcessUpdate(): void
{
$this->dispatcher->expects($this->once())->method('hasListeners')->willReturn(true);
$this->dispatcher->expects($this->once())->method('dispatch')->with(
$this->isInstanceOf(UpdateColumnBackgroundEvent::class),
LeadEvents::LEAD_FIELD_PRE_UPDATE_COLUMN_BACKGROUND_JOB,
);
$fieldColumnBackgroundJobDispatcher = new FieldColumnBackgroundJobDispatcher($this->dispatcher);
$fieldColumnBackgroundJobDispatcher->dispatchPreUpdateColumnEvent(new LeadField());
}
public function testNormalProcessDelete(): void
{
$this->dispatcher->expects($this->once())->method('hasListeners')->willReturn(true);
$this->dispatcher->expects($this->once())->method('dispatch')->with(
$this->isInstanceOf(DeleteColumnBackgroundEvent::class),
LeadEvents::LEAD_FIELD_PRE_DELETE_COLUMN_BACKGROUND_JOB,
);
$fieldColumnBackgroundJobDispatcher = new FieldColumnBackgroundJobDispatcher($this->dispatcher);
$fieldColumnBackgroundJobDispatcher->dispatchPreDeleteColumnEvent(new LeadField());
}
public function testStopPropagation(): void
{
$this->dispatcher->expects($this->once())->method('hasListeners')->willReturn(true);
$this->dispatcher->expects($this->once())->method('dispatch')->with(
$this->callback(function (AddColumnBackgroundEvent $event) {
$event->stopPropagation();
return $event instanceof AddColumnBackgroundEvent;
}),
LeadEvents::LEAD_FIELD_PRE_ADD_COLUMN_BACKGROUND_JOB,
);
$fieldColumnBackgroundJobDispatcher = new FieldColumnBackgroundJobDispatcher($this->dispatcher);
$this->expectException(AbortColumnCreateException::class);
$this->expectExceptionMessage('Column cannot be created now');
$fieldColumnBackgroundJobDispatcher->dispatchPreAddColumnEvent(new LeadField());
}
public function testStopPropagationUpdate(): void
{
$this->dispatcher->expects($this->once())->method('hasListeners')->willReturn(true);
$this->dispatcher->expects($this->once())->method('dispatch')->with(
$this->callback(function (UpdateColumnBackgroundEvent $event) {
$event->stopPropagation();
return true;
}),
LeadEvents::LEAD_FIELD_PRE_UPDATE_COLUMN_BACKGROUND_JOB,
);
$fieldColumnBackgroundJobDispatcher = new FieldColumnBackgroundJobDispatcher($this->dispatcher);
$this->expectException(AbortColumnUpdateException::class);
$this->expectExceptionMessage('Column cannot be updated now');
$fieldColumnBackgroundJobDispatcher->dispatchPreUpdateColumnEvent(new LeadField());
}
public function testStopPropagationDelete(): void
{
$this->dispatcher->expects($this->once())->method('hasListeners')->willReturn(true);
$this->dispatcher->expects($this->once())->method('dispatch')->with(
$this->callback(function (DeleteColumnBackgroundEvent $event) {
$event->stopPropagation();
return $event instanceof DeleteColumnBackgroundEvent;
}),
LeadEvents::LEAD_FIELD_PRE_DELETE_COLUMN_BACKGROUND_JOB,
);
$fieldColumnBackgroundJobDispatcher = new FieldColumnBackgroundJobDispatcher($this->dispatcher);
$this->expectException(AbortColumnUpdateException::class);
$this->expectExceptionMessage('Column cannot be deleted now');
$fieldColumnBackgroundJobDispatcher->dispatchPreDeleteColumnEvent(new LeadField());
}
}

View File

@@ -0,0 +1,131 @@
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Field\Dispatcher;
use Mautic\LeadBundle\Entity\LeadField;
use Mautic\LeadBundle\Field\Dispatcher\FieldColumnDispatcher;
use Mautic\LeadBundle\Field\Event\AddColumnBackgroundEvent;
use Mautic\LeadBundle\Field\Event\AddColumnEvent;
use Mautic\LeadBundle\Field\Event\DeleteColumnEvent;
use Mautic\LeadBundle\Field\Event\UpdateColumnEvent;
use Mautic\LeadBundle\Field\Exception\AbortColumnCreateException;
use Mautic\LeadBundle\Field\Exception\AbortColumnUpdateException;
use Mautic\LeadBundle\Field\Settings\BackgroundSettings;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
class FieldColumnDispatcherTest extends \PHPUnit\Framework\TestCase
{
public function testNoBackground(): void
{
$dispatcher = $this->createMock(EventDispatcherInterface::class);
$backgroundSettings = $this->createMock(BackgroundSettings::class);
$leadField = new LeadField();
$backgroundSettings->expects($this->once())
->method('shouldProcessColumnChangeInBackground')
->willReturn(false);
$dispatcher->expects($this->once())
->method('dispatch')
->with(
$this->isInstanceOf(AddColumnEvent::class),
'mautic.lead_field_pre_add_column',
);
$fieldColumnDispatcher = new FieldColumnDispatcher($dispatcher, $backgroundSettings);
$fieldColumnDispatcher->dispatchPreAddColumnEvent($leadField);
}
public function testStopPropagation(): void
{
$leadField = new LeadField();
$dispatcher = $this->createMock(EventDispatcherInterface::class);
$backgroundSettings = $this->createMock(BackgroundSettings::class);
$backgroundSettings->expects($this->once())
->method('shouldProcessColumnChangeInBackground')
->willReturn(true);
$dispatcher->expects($this->once())
->method('dispatch')
->with(
$this->isInstanceOf(AddColumnEvent::class),
'mautic.lead_field_pre_add_column'
);
$fieldColumnDispatcher = new FieldColumnDispatcher($dispatcher, $backgroundSettings);
$this->expectException(AbortColumnCreateException::class);
$this->expectExceptionMessage('Column change will be processed in background job');
$fieldColumnDispatcher->dispatchPreAddColumnEvent($leadField);
}
public function testStopPropagationUpdate(): void
{
$leadField = new LeadField();
$dispatcher = $this->createMock(EventDispatcherInterface::class);
$backgroundSettings = $this->createMock(BackgroundSettings::class);
$dispatcher
->expects($this->once())
->method('hasListeners')
->willReturn(true);
$backgroundSettings
->expects($this->once())
->method('shouldProcessColumnChangeInBackground')
->willReturn(true);
$dispatcher
->expects($this->once())
->method('dispatch')
->with(
$this->callback(function ($event) {
/* @var AddColumnBackgroundEvent $event */
return $event instanceof UpdateColumnEvent;
}),
'mautic.lead_field_pre_update_column'
);
$fieldColumnDispatcher = new FieldColumnDispatcher($dispatcher, $backgroundSettings);
$this->expectException(AbortColumnUpdateException::class);
$this->expectExceptionMessage('Column change will be processed in background job');
$fieldColumnDispatcher->dispatchPreUpdateColumnEvent($leadField);
}
public function testStopPropagationDelete(): void
{
$leadField = new LeadField();
$dispatcher = $this->createMock(EventDispatcherInterface::class);
$backgroundSettings = $this->createMock(BackgroundSettings::class);
$dispatcher->expects($this->once())
->method('hasListeners')
->willReturn(true);
$backgroundSettings->expects($this->once())
->method('shouldProcessColumnChangeInBackground')
->willReturn(true);
$dispatcher->expects($this->once())
->method('dispatch')
->with(
$this->callback(fn ($event) => $event instanceof DeleteColumnEvent),
'mautic.lead_field_pre_delete_column',
);
$fieldColumnDispatcher = new FieldColumnDispatcher($dispatcher, $backgroundSettings);
$this->expectException(AbortColumnUpdateException::class);
$this->expectExceptionMessage('Column delete will be processed in background job');
$fieldColumnDispatcher->dispatchPreDeleteColumnEvent($leadField);
}
}

View File

@@ -0,0 +1,70 @@
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Field\Dispatcher;
use Doctrine\ORM\EntityManager;
use Mautic\LeadBundle\Entity\LeadField;
use Mautic\LeadBundle\Event\LeadFieldEvent;
use Mautic\LeadBundle\Field\Dispatcher\FieldDeleteDispatcher;
use Mautic\LeadBundle\Field\Exception\AbortColumnUpdateException;
use Mautic\LeadBundle\Field\Settings\BackgroundSettings;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
final class FieldDeleteDispatcherTest extends TestCase
{
/**
* @var MockObject&EventDispatcherInterface
*/
private MockObject $dispatcherMock;
/**
* @var MockObject&EntityManager
*/
private MockObject $entityManagerMock;
/**
* @var MockObject&BackgroundSettings
*/
private $backgroundSettingsMock;
private FieldDeleteDispatcher $fieldDeleteDispatcher;
protected function setUp(): void
{
$this->dispatcherMock = $this->createMock(EventDispatcherInterface::class);
$this->entityManagerMock = $this->createMock(EntityManager::class);
$this->backgroundSettingsMock = $this->createMock(BackgroundSettings::class);
$this->fieldDeleteDispatcher = new FieldDeleteDispatcher(
$this->dispatcherMock,
$this->entityManagerMock,
$this->backgroundSettingsMock
);
}
public function testDispatchPreDeleteEventInBackground(): void
{
$this->backgroundSettingsMock->expects($this->once())->method('shouldProcessColumnChangeInBackground')->willReturn(true);
$leadField = new LeadField();
$this->expectException(AbortColumnUpdateException::class);
$this->expectExceptionMessage('Column change will be processed in background job');
$this->fieldDeleteDispatcher->dispatchPreDeleteEvent($leadField);
}
public function testDispatchPreDeleteEventNow(): void
{
$this->backgroundSettingsMock->expects($this->once())->method('shouldProcessColumnChangeInBackground')->willReturn(false);
$leadField = new LeadField();
$this->dispatcherMock->expects($this->once())->method('hasListeners')->willReturn(true);
$this->dispatcherMock->expects($this->once())->method('dispatch')->with(
$this->callback(fn ($event) => $event instanceof LeadFieldEvent),
'mautic.lead_field_pre_delete',
);
$this->fieldDeleteDispatcher->dispatchPreDeleteEvent($leadField);
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace Mautic\LeadBundle\Tests\Field;
use Mautic\LeadBundle\Field\FieldList;
use Mautic\LeadBundle\Field\FieldsWithUniqueIdentifier;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
class FieldsWithUniqueIdentifierTest extends TestCase
{
/**
* @var MockObject|FieldList
*/
private $fieldList;
/**
* @var FieldsWithUniqueIdentifier
*/
private $fieldsWithUniqueIdentifier;
protected function setUp(): void
{
parent::setUp();
$this->fieldList = $this->createMock(FieldList::class);
$this->fieldsWithUniqueIdentifier = new FieldsWithUniqueIdentifier($this->fieldList);
}
public function testCacheIsUsed(): void
{
$fields = ['cached fields'];
$this->fieldList->expects($this->once())
->method('getFieldList')
->willReturn($fields);
Assert::assertSame($fields, $this->fieldsWithUniqueIdentifier->getFieldsWithUniqueIdentifier(['isPublished' => false]));
// The cache should be used on subsequent requests and a second call to getFieldList not made
Assert::assertSame($fields, $this->fieldsWithUniqueIdentifier->getFieldsWithUniqueIdentifier(['isPublished' => false]));
}
public function testCacheIsNotUsed(): void
{
$fields = ['cached fields'];
$this->fieldList->expects($this->exactly(2))
->method('getFieldList')
->willReturn($fields);
Assert::assertSame($fields, $this->fieldsWithUniqueIdentifier->getLiveFields(['isPublished' => false]));
// The cache should not be used on subsequent requests
Assert::assertSame($fields, $this->fieldsWithUniqueIdentifier->getLiveFields(['isPublished' => false]));
}
}

View File

@@ -0,0 +1,76 @@
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Field\Helper;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Result;
use Doctrine\DBAL\Statement;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Mapping\ClassMetadata;
use Mautic\LeadBundle\Entity\Lead;
use Mautic\LeadBundle\Field\Helper\IndexHelper;
class IndexHelperTest extends \PHPUnit\Framework\TestCase
{
public const COLUMN_NAME_KEY = 'Column_name';
public function testGetIndexCountAndColumns(): void
{
$tableName = 'table_name';
$sql = "SHOW INDEXES FROM `$tableName`";
$columnNames = [
'id', '0', '1', '1', '2', '2',
];
foreach ($columnNames as $columnName) {
$sqlResult[][self::COLUMN_NAME_KEY] = $columnName;
}
$expectedColumnNames = array_map(
function ($column) {
return $column[self::COLUMN_NAME_KEY];
},
$sqlResult
);
$expectedCount = count($expectedColumnNames);
$emMock = $this->createMock(EntityManager::class);
$helper = new IndexHelper($emMock);
$mdMock = $this->createMock(ClassMetadata::class);
$emMock->expects($this->once())
->method('getClassMetadata')
->with(Lead::class)
->willReturn($mdMock);
$mdMock->expects($this->once())
->method('getTableName')
->willReturn($tableName);
$connMock = $this->createMock(Connection::class);
$emMock->expects($this->once())
->method('getConnection')
->willReturn($connMock);
$stmtMock = $this->createMock(Statement::class);
$result = $this->createMock(Result::class);
$connMock->expects($this->once())
->method('prepare')
->with($sql)
->willReturn($stmtMock);
$stmtMock->expects($this->once())
->method('executeQuery')
->willReturn($result);
$result->expects($this->once())
->method('fetchAllAssociative')
->willReturn($sqlResult);
$this->assertEquals($expectedColumnNames, $helper->getIndexedColumnNames());
$this->assertEquals($expectedCount, $helper->getIndexCount());
}
}

View File

@@ -0,0 +1,163 @@
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Field;
use Mautic\LeadBundle\Field\FieldList;
use Mautic\LeadBundle\Field\FieldsWithUniqueIdentifier;
use Mautic\LeadBundle\Field\IdentifierFields;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
class IdentifierFieldsTest extends TestCase
{
/**
* @var FieldsWithUniqueIdentifier&MockObject
*/
private MockObject $fieldsWithUniqueIdentifiers;
/**
* @var FieldList&MockObject
*/
private MockObject $fieldList;
private IdentifierFields $identifierFields;
protected function setUp(): void
{
$this->fieldsWithUniqueIdentifiers = $this->createMock(FieldsWithUniqueIdentifier::class);
$this->fieldList = $this->createMock(FieldList::class);
$this->identifierFields = new IdentifierFields($this->fieldsWithUniqueIdentifiers, $this->fieldList);
}
public function testLeadObjectReturnsDefaultFields(): void
{
$this->fieldsWithUniqueIdentifiers->expects($this->once())
->method('getFieldsWithUniqueIdentifier')
->with(['object' => 'lead'])
->willReturn([]);
$this->fieldList->expects($this->once())
->method('getFieldList')
->with(true, false, ['isPublished' => true, 'object' => 'lead'])
->willReturn([]);
$fields = $this->identifierFields->getFieldList('lead');
$this->assertEquals(
[
'firstname',
'lastname',
'company',
'email',
],
$fields
);
}
public function testCompanyObjectReturnsDefaultFields(): void
{
$this->fieldsWithUniqueIdentifiers->expects($this->once())
->method('getFieldsWithUniqueIdentifier')
->with(['object' => 'company'])
->willReturn([]);
$this->fieldList->expects($this->once())
->method('getFieldList')
->with(true, false, ['isPublished' => true, 'object' => 'company'])
->willReturn([]);
$fields = $this->identifierFields->getFieldList('company');
$this->assertEquals(
[
'companyname',
'companyemail',
'companywebsite',
'city',
'state',
'country',
],
$fields
);
}
public function testUniqueIdentifiersAreIncluded(): void
{
$this->fieldsWithUniqueIdentifiers->expects($this->once())
->method('getFieldsWithUniqueIdentifier')
->with(['object' => 'lead'])
->willReturn(
[
'unique_id' => 'Unique ID',
]
);
$this->fieldList->expects($this->once())
->method('getFieldList')
->with(true, false, ['isPublished' => true, 'object' => 'lead'])
->willReturn([]);
$fields = $this->identifierFields->getFieldList('lead');
$this->assertEquals(
[
'firstname',
'lastname',
'company',
'email',
'unique_id',
],
$fields
);
}
public function testSocialFieldsAreIncluded(): void
{
$this->fieldsWithUniqueIdentifiers->expects($this->once())
->method('getFieldsWithUniqueIdentifier')
->with(['object' => 'lead'])
->willReturn(
[
'unique_id' => 'Unique ID',
]
);
$this->fieldList->expects($this->once())
->method('getFieldList')
->with(true, false, ['isPublished' => true, 'object' => 'lead'])
->willReturn(
[
'Social' => [
'twitter' => [
'alias' => 'twitter',
'label' => 'Twitter',
'type' => 'text',
],
],
'Core' => [
'foo' => [
'alias' => 'foo',
'label' => 'Foo',
'type' => 'text',
],
],
]
);
$fields = $this->identifierFields->getFieldList('lead');
$this->assertEquals(
[
'firstname',
'lastname',
'company',
'email',
'unique_id',
'twitter',
],
$fields
);
}
}

View File

@@ -0,0 +1,81 @@
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Field;
use Mautic\CoreBundle\Helper\UserHelper;
use Mautic\LeadBundle\Entity\LeadField;
use Mautic\LeadBundle\Entity\LeadFieldRepository;
use Mautic\LeadBundle\Exception\NoListenerException;
use Mautic\LeadBundle\Field\Dispatcher\FieldDeleteDispatcher;
use Mautic\LeadBundle\Field\Exception\AbortColumnUpdateException;
use Mautic\LeadBundle\Field\LeadFieldDeleter;
use PHPUnit\Framework\MockObject\MockObject;
use PHPUnit\Framework\TestCase;
final class LeadFieldDeleterTest extends TestCase
{
/**
* @var MockObject&LeadFieldRepository
*/
private MockObject $leadFieldRepositoryMock;
/**
* @var MockObject&FieldDeleteDispatcher
*/
private MockObject $fieldDeleteDispatcherMock;
/**
* @var MockObject&UserHelper
*/
private MockObject $userHelperMock;
private LeadFieldDeleter $leadFieldDeleter;
protected function setUp(): void
{
$this->leadFieldRepositoryMock = $this->createMock(LeadFieldRepository::class);
$this->fieldDeleteDispatcherMock = $this->createMock(FieldDeleteDispatcher::class);
$this->userHelperMock = $this->createMock(UserHelper::class);
$this->leadFieldDeleter = new LeadFieldDeleter(
$this->leadFieldRepositoryMock,
$this->fieldDeleteDispatcherMock,
$this->userHelperMock,
);
}
public function testDeleteLeadFieldEntityNoBackground(): void
{
$leadField = new LeadField();
$this->fieldDeleteDispatcherMock
->expects($this->once())
->method('dispatchPreDeleteEvent')
->with($leadField)
->willThrowException(new AbortColumnUpdateException());
$this->leadFieldRepositoryMock
->expects($this->never())
->method('deleteEntity');
$this->leadFieldDeleter->deleteLeadFieldEntity($leadField, false);
}
public function testDeleteLeadFieldEntityInBackground(): void
{
$leadField = new LeadField();
$this->fieldDeleteDispatcherMock
->expects($this->once())
->method('dispatchPreDeleteEvent')
->with($leadField)
->willThrowException(new AbortColumnUpdateException());
$this->leadFieldRepositoryMock
->expects($this->once())
->method('deleteEntity')
->with($leadField);
$this->fieldDeleteDispatcherMock
->expects($this->once())
->method('dispatchPostDeleteEvent')
->with($leadField)
->willThrowException(new NoListenerException());
$this->leadFieldDeleter->deleteLeadFieldEntity($leadField, true);
}
}

View File

@@ -0,0 +1,55 @@
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Field;
use Mautic\LeadBundle\Entity\LeadField;
use Mautic\LeadBundle\Entity\LeadFieldRepository;
use Mautic\LeadBundle\Field\Dispatcher\FieldSaveDispatcher;
use Mautic\LeadBundle\Field\LeadFieldSaver;
class LeadFieldSaverTest extends \PHPUnit\Framework\TestCase
{
public function testSave(): void
{
$leadFieldRepository = $this->createMock(LeadFieldRepository::class);
$fieldSaveDispatcher = $this->createMock(FieldSaveDispatcher::class);
$leadFieldSaver = new LeadFieldSaver($leadFieldRepository, $fieldSaveDispatcher);
$leadField = new LeadField();
$fieldSaveDispatcher->expects($this->once())
->method('dispatchPreSaveEvent')
->with($leadField, true);
$fieldSaveDispatcher->expects($this->once())
->method('dispatchPostSaveEvent')
->with($leadField, true);
$leadFieldSaver->saveLeadFieldEntity($leadField, true);
}
public function testSaveNoColumnCreated(): void
{
$leadFieldRepository = $this->createMock(LeadFieldRepository::class);
$fieldSaveDispatcher = $this->createMock(FieldSaveDispatcher::class);
$leadFieldSaver = new LeadFieldSaver($leadFieldRepository, $fieldSaveDispatcher);
$leadField = new LeadField();
$fieldSaveDispatcher->expects($this->once())
->method('dispatchPreSaveEvent')
->with($leadField, true);
$fieldSaveDispatcher->expects($this->once())
->method('dispatchPostSaveEvent')
->with($leadField, true);
$leadFieldSaver->saveLeadFieldEntityWithoutColumnCreated($leadField);
$this->assertTrue($leadField->getColumnIsNotCreated());
}
}

View File

@@ -0,0 +1,123 @@
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Field\Notification;
use Mautic\CoreBundle\Model\NotificationModel;
use Mautic\LeadBundle\Entity\LeadField;
use Mautic\LeadBundle\Field\Notification\CustomFieldNotification;
use Mautic\UserBundle\Entity\User;
use Mautic\UserBundle\Model\UserModel;
use Symfony\Contracts\Translation\TranslatorInterface;
class CustomFieldNotificationTest extends \PHPUnit\Framework\TestCase
{
public function testNoUserId(): void
{
$notificationModel = $this->createMock(NotificationModel::class);
$userModel = $this->createMock(UserModel::class);
$translatorInterface = $this->createMock(TranslatorInterface::class);
$leadField = new LeadField();
$userModel->expects($this->never())
->method('getEntity');
$customFieldNotification = new CustomFieldNotification($notificationModel, $userModel, $translatorInterface);
$customFieldNotification->customFieldWasCreated($leadField, 0);
}
public function testNoUser(): void
{
$notificationModel = $this->createMock(NotificationModel::class);
$userModel = $this->createMock(UserModel::class);
$translatorInterface = $this->createMock(TranslatorInterface::class);
$leadField = new LeadField();
$userModel->expects($this->once())
->method('getEntity')
->willReturn(null);
$translatorInterface->expects($this->never())
->method('trans');
$customFieldNotification = new CustomFieldNotification($notificationModel, $userModel, $translatorInterface);
$customFieldNotification->customFieldWasCreated($leadField, 1);
}
public function testCustomFieldWasCreated(): void
{
$notificationModel = $this->createMock(NotificationModel::class);
$userModel = $this->createMock(UserModel::class);
$translatorInterface = $this->createMock(TranslatorInterface::class);
$userId = 1;
$leadField = new LeadField();
$user = new User();
$userModel->expects($this->once())
->method('getEntity')
->with($userId)
->willReturn($user);
$translatorInterface->expects($this->exactly(2))
->method('trans')
->willReturn('text');
$notificationModel->expects($this->once())
->method('addNotification')
->with(
'text',
'info',
false,
'text',
'ri-layout-column-line',
null,
$user
);
$customFieldNotification = new CustomFieldNotification($notificationModel, $userModel, $translatorInterface);
$customFieldNotification->customFieldWasCreated($leadField, $userId);
}
public function testCustomFieldWasDeleted(): void
{
$notificationModel = $this->createMock(NotificationModel::class);
$userModel = $this->createMock(UserModel::class);
$translatorInterface = $this->createMock(TranslatorInterface::class);
$userId = 1;
$leadField = new LeadField();
$user = new User();
$userModel->expects($this->once())
->method('getEntity')
->with($userId)
->willReturn($user);
$translatorInterface->expects($this->exactly(2))
->method('trans')
->willReturn('textDelete');
$notificationModel->expects($this->once())
->method('addNotification')
->with(
'textDelete',
'info',
false,
'textDelete',
'ri-layout-column-line',
null,
$user
);
$customFieldNotification = new CustomFieldNotification($notificationModel, $userModel, $translatorInterface);
$customFieldNotification->customFieldWasDeleted($leadField, $userId);
}
}

View File

@@ -0,0 +1,220 @@
<?php
declare(strict_types=1);
namespace Mautic\LeadBundle\Tests\Field;
use Mautic\CoreBundle\Doctrine\Mapping\ClassMetadataBuilder;
use Mautic\LeadBundle\Field\SchemaDefinition;
use PHPUnit\Framework\Assert;
use PHPUnit\Framework\TestCase;
class SchemaDefinitionTest extends TestCase
{
/**
* @param mixed[] $expected
*/
#[\PHPUnit\Framework\Attributes\DataProvider('dataGetSchemaDefinition')]
public function testGetSchemaDefinition(string $alias, string $type, bool $isUnique, ?int $length, array $expected): void
{
Assert::assertSame($expected, SchemaDefinition::getSchemaDefinition($alias, $type, $isUnique, $length));
Assert::assertSame($expected, (new SchemaDefinition())->getSchemaDefinitionNonStatic($alias, $type, $isUnique, $length));
}
/**
* @return mixed[]
*/
public static function dataGetSchemaDefinition(): iterable
{
foreach (['datetime', 'date', 'time', 'boolean'] as $type) {
yield [
'some',
$type,
false,
80,
[
'name' => 'some',
'type' => $type,
'options' => ['notnull' => false],
],
];
}
yield [
'some',
'number',
false,
70,
[
'name' => 'some',
'type' => 'float',
'options' => [
'notnull' => false,
],
],
];
foreach (['timezone', 'locale', 'country', 'email', 'lookup', 'select', 'region', 'tel', 'text'] as $type) {
foreach ([75, null] as $length) {
$maxLength = ('text' == $type || !is_null($length)) ? $length : SchemaDefinition::MAX_VARCHAR_LENGTH;
yield [
'some',
$type,
false,
$maxLength,
[
'name' => 'some',
'type' => 'string',
'options' => [
'notnull' => false,
'length' => $maxLength ?? 191,
],
],
];
}
}
foreach (['description' => 'text', 'descriptionOfArticle' => 'text'] as $alias => $type) {
yield [
$alias,
'text',
false,
null,
[
'name' => $alias,
'type' => $type,
'options' => [
'notnull' => false,
'length' => null,
],
],
];
}
yield [
'articleDescription',
'text',
false,
null,
[
'name' => 'articleDescription',
'type' => 'string',
'options' => [
'notnull' => false,
'length' => 191,
],
],
];
yield [
'some',
'multiselect',
false,
80,
[
'name' => 'some',
'type' => 'text',
'options' => ['notnull' => false, 'length' => 65535],
],
];
foreach (['html', 'unknown'] as $type) {
yield [
'some',
$type,
false,
80,
[
'name' => 'some',
'type' => 'text',
'options' => ['notnull' => false],
],
];
}
$allTypes = [
'datetime',
'date',
'time',
'boolean',
'number',
'timezone',
'locale',
'country',
'email',
'lookup',
'select',
'region',
'tel',
'text',
'multiselect',
'html',
'unknown',
];
foreach ($allTypes as $type) {
yield [
'some',
$type,
true,
80,
[
'name' => 'some',
'type' => 'string',
'options' => ['notnull' => false],
],
];
}
}
/**
* @param mixed[] $schemaDefinition
*/
#[\PHPUnit\Framework\Attributes\DataProvider('dataGetFieldCharLengthLimit')]
public function testGetFieldCharLengthLimit(array $schemaDefinition, ?int $expected): void
{
Assert::assertSame($expected, SchemaDefinition::getFieldCharLengthLimit($schemaDefinition));
}
/**
* @return mixed[]
*/
public static function dataGetFieldCharLengthLimit(): iterable
{
yield [
[
'type' => 'string',
'options' => [
'length' => 50,
],
],
50,
];
yield [
[
'type' => 'string',
],
ClassMetadataBuilder::MAX_VARCHAR_INDEXED_LENGTH,
];
yield [
[
'type' => 'text',
'options' => [
'length' => 60,
],
],
60,
];
foreach (['text', 'datetime', 'date', 'time', 'boolean', 'float'] as $type) {
yield [
[
'type' => $type,
],
null,
];
}
}
}