Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment;
|
||||
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(ContactSegmentFilterCrate::class)]
|
||||
class ContactSegmentFilterCrateTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testEmptyFilter(): void
|
||||
{
|
||||
$filter = [];
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
|
||||
$this->assertNull($contactSegmentFilterCrate->getGlue());
|
||||
$this->assertNull($contactSegmentFilterCrate->getField());
|
||||
$this->assertTrue($contactSegmentFilterCrate->isContactType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isCompanyType());
|
||||
$this->assertNull($contactSegmentFilterCrate->getFilter());
|
||||
$this->assertNull($contactSegmentFilterCrate->getOperator());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isBooleanType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isDateType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->hasTimeParts());
|
||||
}
|
||||
|
||||
public function testDateIdentifiedFilter(): void
|
||||
{
|
||||
$filter = [
|
||||
'glue' => 'and',
|
||||
'field' => 'date_identified',
|
||||
'object' => 'lead',
|
||||
'type' => 'datetime',
|
||||
'filter' => null,
|
||||
'display' => null,
|
||||
'operator' => '!empty',
|
||||
];
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
|
||||
$this->assertSame('and', $contactSegmentFilterCrate->getGlue());
|
||||
$this->assertSame('date_identified', $contactSegmentFilterCrate->getField());
|
||||
$this->assertTrue($contactSegmentFilterCrate->isContactType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isCompanyType());
|
||||
$this->assertNull($contactSegmentFilterCrate->getFilter());
|
||||
$this->assertSame('!empty', $contactSegmentFilterCrate->getOperator());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isBooleanType());
|
||||
$this->assertTrue($contactSegmentFilterCrate->isDateType());
|
||||
$this->assertTrue($contactSegmentFilterCrate->hasTimeParts());
|
||||
}
|
||||
|
||||
public function testDateFilter(): void
|
||||
{
|
||||
$filter = [
|
||||
'glue' => 'and',
|
||||
'field' => 'date_identified',
|
||||
'object' => 'lead',
|
||||
'type' => 'date',
|
||||
'filter' => null,
|
||||
'display' => null,
|
||||
'operator' => '!empty',
|
||||
];
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
|
||||
$this->assertSame('and', $contactSegmentFilterCrate->getGlue());
|
||||
$this->assertSame('date_identified', $contactSegmentFilterCrate->getField());
|
||||
$this->assertTrue($contactSegmentFilterCrate->isContactType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isCompanyType());
|
||||
$this->assertNull($contactSegmentFilterCrate->getFilter());
|
||||
$this->assertSame('!empty', $contactSegmentFilterCrate->getOperator());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isBooleanType());
|
||||
$this->assertTrue($contactSegmentFilterCrate->isDateType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->hasTimeParts());
|
||||
}
|
||||
|
||||
public function testBooleanFilter(): void
|
||||
{
|
||||
$filter = [
|
||||
'type' => 'boolean',
|
||||
'filter' => '1',
|
||||
];
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
|
||||
$this->assertTrue($contactSegmentFilterCrate->getFilter());
|
||||
$this->assertTrue($contactSegmentFilterCrate->isBooleanType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isDateType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->hasTimeParts());
|
||||
$this->assertTrue($contactSegmentFilterCrate->filterValueDoNotNeedAdjustment());
|
||||
}
|
||||
|
||||
public function testNumericFilter(): void
|
||||
{
|
||||
$filter = [
|
||||
'type' => 'number',
|
||||
'filter' => '2',
|
||||
];
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
|
||||
$this->assertSame(2.0, $contactSegmentFilterCrate->getFilter());
|
||||
$this->assertTrue($contactSegmentFilterCrate->isNumberType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isDateType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->hasTimeParts());
|
||||
$this->assertTrue($contactSegmentFilterCrate->filterValueDoNotNeedAdjustment());
|
||||
}
|
||||
|
||||
public function testCompanyTypeFilter(): void
|
||||
{
|
||||
$filter = [
|
||||
'object' => 'company',
|
||||
];
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
|
||||
$this->assertFalse($contactSegmentFilterCrate->isContactType());
|
||||
$this->assertTrue($contactSegmentFilterCrate->isCompanyType());
|
||||
}
|
||||
|
||||
public function testMultiselectFilter(): void
|
||||
{
|
||||
$filter = [
|
||||
'glue' => 'and',
|
||||
'field' => 'multiselect_cf',
|
||||
'object' => 'lead',
|
||||
'type' => 'multiselect',
|
||||
'filter' => [2, 4],
|
||||
'display' => null,
|
||||
'operator' => 'in',
|
||||
];
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
|
||||
$this->assertSame('and', $contactSegmentFilterCrate->getGlue());
|
||||
$this->assertSame('multiselect_cf', $contactSegmentFilterCrate->getField());
|
||||
$this->assertTrue($contactSegmentFilterCrate->isContactType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isCompanyType());
|
||||
$this->assertSame([2, 4], $contactSegmentFilterCrate->getFilter());
|
||||
$this->assertSame('multiselect', $contactSegmentFilterCrate->getOperator());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isBooleanType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isDateType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->hasTimeParts());
|
||||
}
|
||||
|
||||
public function testNotMultiselectFilter(): void
|
||||
{
|
||||
$filter = [
|
||||
'glue' => 'and',
|
||||
'field' => 'multiselect_cf',
|
||||
'object' => 'lead',
|
||||
'type' => 'multiselect',
|
||||
'filter' => [2, 4],
|
||||
'display' => null,
|
||||
'operator' => '!in',
|
||||
];
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
|
||||
$this->assertSame('and', $contactSegmentFilterCrate->getGlue());
|
||||
$this->assertSame('multiselect_cf', $contactSegmentFilterCrate->getField());
|
||||
$this->assertTrue($contactSegmentFilterCrate->isContactType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isCompanyType());
|
||||
$this->assertSame([2, 4], $contactSegmentFilterCrate->getFilter());
|
||||
$this->assertSame('!multiselect', $contactSegmentFilterCrate->getOperator());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isBooleanType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isDateType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->hasTimeParts());
|
||||
}
|
||||
|
||||
public function testOldEqualInsteadOfInOperator(): void
|
||||
{
|
||||
$filter = [
|
||||
'glue' => 'and',
|
||||
'field' => 'tags',
|
||||
'object' => 'lead',
|
||||
'type' => 'tags',
|
||||
'filter' => [3],
|
||||
'display' => null,
|
||||
'operator' => '=',
|
||||
];
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
|
||||
$this->assertSame('and', $contactSegmentFilterCrate->getGlue());
|
||||
$this->assertSame('tags', $contactSegmentFilterCrate->getField());
|
||||
$this->assertTrue($contactSegmentFilterCrate->isContactType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isCompanyType());
|
||||
$this->assertSame([3], $contactSegmentFilterCrate->getFilter());
|
||||
$this->assertSame('in', $contactSegmentFilterCrate->getOperator());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isBooleanType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isDateType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->hasTimeParts());
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('specialFieldsToConvertToEmptyProvider')]
|
||||
public function testSpecialFieldsToConvertToNotEmpty($field): void
|
||||
{
|
||||
$filter = [
|
||||
'glue' => 'and',
|
||||
'field' => $field,
|
||||
'object' => 'lead',
|
||||
'type' => 'boolean',
|
||||
'filter' => 1,
|
||||
'display' => null,
|
||||
'operator' => '=',
|
||||
];
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
|
||||
$this->assertSame('and', $contactSegmentFilterCrate->getGlue());
|
||||
$this->assertSame($field, $contactSegmentFilterCrate->getField());
|
||||
$this->assertTrue($contactSegmentFilterCrate->isContactType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isCompanyType());
|
||||
$this->assertTrue($contactSegmentFilterCrate->getFilter());
|
||||
$this->assertSame('notEmpty', $contactSegmentFilterCrate->getOperator());
|
||||
$this->assertTrue($contactSegmentFilterCrate->isBooleanType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isDateType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->hasTimeParts());
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('specialFieldsToConvertToEmptyProvider')]
|
||||
public function testSpecialFieldsToConvertToEmpty($field): void
|
||||
{
|
||||
$filter = [
|
||||
'glue' => 'and',
|
||||
'field' => $field,
|
||||
'object' => 'lead',
|
||||
'type' => 'boolean',
|
||||
'filter' => 0,
|
||||
'display' => null,
|
||||
'operator' => '=',
|
||||
];
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
|
||||
$this->assertSame('and', $contactSegmentFilterCrate->getGlue());
|
||||
$this->assertSame($field, $contactSegmentFilterCrate->getField());
|
||||
$this->assertTrue($contactSegmentFilterCrate->isContactType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isCompanyType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->getFilter());
|
||||
$this->assertSame('empty', $contactSegmentFilterCrate->getOperator());
|
||||
$this->assertTrue($contactSegmentFilterCrate->isBooleanType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isDateType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->hasTimeParts());
|
||||
}
|
||||
|
||||
public static function specialFieldsToConvertToEmptyProvider()
|
||||
{
|
||||
return [
|
||||
['page_id'],
|
||||
['email_id'],
|
||||
['redirect_id'],
|
||||
['notification'],
|
||||
];
|
||||
}
|
||||
|
||||
public function testBehaviorsTypeFilter(): void
|
||||
{
|
||||
$filter = [
|
||||
'object' => 'behaviors',
|
||||
];
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
|
||||
$this->assertFalse($contactSegmentFilterCrate->isContactType());
|
||||
$this->assertFalse($contactSegmentFilterCrate->isCompanyType());
|
||||
$this->assertTrue($contactSegmentFilterCrate->isBehaviorsType());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment;
|
||||
|
||||
use Mautic\LeadBundle\Entity\LeadList;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterFactory;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilters;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DecoratorFactory;
|
||||
use Mautic\LeadBundle\Segment\Decorator\FilterDecoratorInterface;
|
||||
use Mautic\LeadBundle\Segment\Query\Filter\FilterQueryBuilderInterface;
|
||||
use Mautic\LeadBundle\Segment\TableSchemaColumnsCache;
|
||||
use Symfony\Component\DependencyInjection\Container;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(ContactSegmentFilterFactory::class)]
|
||||
class ContactSegmentFilterFactoryTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testLeadFilter(): void
|
||||
{
|
||||
$tableSchemaColumnsCache = $this->createMock(TableSchemaColumnsCache::class);
|
||||
$container = $this->createMock(Container::class);
|
||||
$decoratorFactory = $this->createMock(DecoratorFactory::class);
|
||||
|
||||
$filterDecorator = $this->createMock(FilterDecoratorInterface::class);
|
||||
$decoratorFactory->expects($this->exactly(6))
|
||||
->method('getDecoratorForFilter')
|
||||
->willReturn($filterDecorator);
|
||||
|
||||
$filterDecorator->expects($this->exactly(6))
|
||||
->method('getQueryType')
|
||||
->willReturn('MyQueryTypeId');
|
||||
|
||||
$filterQueryBuilder = $this->createMock(FilterQueryBuilderInterface::class);
|
||||
$container->expects($this->exactly(6))
|
||||
->method('get')
|
||||
->with('MyQueryTypeId')
|
||||
->willReturn($filterQueryBuilder);
|
||||
|
||||
$contactSegmentFilterFactory = new ContactSegmentFilterFactory($tableSchemaColumnsCache, $container, $decoratorFactory, $this->createMock(EventDispatcherInterface::class));
|
||||
|
||||
$leadList = new LeadList();
|
||||
$leadList->setFilters([
|
||||
[
|
||||
'glue' => 'and',
|
||||
'field' => 'date_identified',
|
||||
'object' => 'lead',
|
||||
'type' => 'datetime',
|
||||
'filter' => null,
|
||||
'display' => null,
|
||||
'operator' => '!empty',
|
||||
],
|
||||
[
|
||||
'glue' => 'and',
|
||||
'type' => 'text',
|
||||
'field' => 'hit_url',
|
||||
'operator' => 'like',
|
||||
'filter' => 'test.com',
|
||||
'display' => '',
|
||||
],
|
||||
[
|
||||
'glue' => 'or',
|
||||
'type' => 'lookup',
|
||||
'field' => 'state',
|
||||
'operator' => '=',
|
||||
'filter' => 'QLD',
|
||||
'display' => '',
|
||||
],
|
||||
[
|
||||
'glue' => 'or',
|
||||
'type' => 'lookup',
|
||||
'field' => 'state',
|
||||
'operator' => ContactSegmentFilterFactory::CUSTOM_OPERATOR,
|
||||
'properties' => [
|
||||
[
|
||||
'operator' => '=',
|
||||
'filter' => 'QLD',
|
||||
],
|
||||
],
|
||||
'merged_property' => [],
|
||||
],
|
||||
[
|
||||
'glue' => 'and',
|
||||
'field' => 'city',
|
||||
'object' => 'lead',
|
||||
'type' => 'text',
|
||||
'filter' => null,
|
||||
'display' => null,
|
||||
'operator' => 'empty',
|
||||
],
|
||||
[
|
||||
'glue' => 'and',
|
||||
'field' => 'city',
|
||||
'object' => 'lead',
|
||||
'type' => 'text',
|
||||
'filter' => null,
|
||||
'display' => null,
|
||||
'operator' => '!empty',
|
||||
],
|
||||
]);
|
||||
|
||||
$contactSegmentFilters = $contactSegmentFilterFactory->getSegmentFilters($leadList);
|
||||
|
||||
$this->assertInstanceOf(ContactSegmentFilters::class, $contactSegmentFilters);
|
||||
$this->assertCount(6, $contactSegmentFilters);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,471 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment;
|
||||
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilter;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\BaseDecorator;
|
||||
use Mautic\LeadBundle\Segment\Decorator\CompanyDecorator;
|
||||
use Mautic\LeadBundle\Segment\Decorator\FilterDecoratorInterface;
|
||||
use Mautic\LeadBundle\Segment\Exception\FieldNotFoundException;
|
||||
use Mautic\LeadBundle\Segment\Query\Filter\FilterQueryBuilderInterface;
|
||||
use Mautic\LeadBundle\Segment\Query\QueryBuilder;
|
||||
use Mautic\LeadBundle\Segment\TableSchemaColumnsCache;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class ContactSegmentFilterTest extends TestCase
|
||||
{
|
||||
private ContactSegmentFilterCrate $contactSegmentFilterCrate;
|
||||
|
||||
/**
|
||||
* @var FilterDecoratorInterface&MockObject
|
||||
*/
|
||||
private MockObject $filterDecorator;
|
||||
|
||||
/**
|
||||
* @var TableSchemaColumnsCache|MockObject
|
||||
*/
|
||||
private MockObject $tableSchemaColumnCache;
|
||||
|
||||
/**
|
||||
* @var FilterQueryBuilderInterface&MockObject
|
||||
*/
|
||||
private MockObject $filterQueryBuilder;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->contactSegmentFilterCrate = new ContactSegmentFilterCrate([]);
|
||||
$this->filterDecorator = $this->createMock(BaseDecorator::class);
|
||||
$this->tableSchemaColumnCache = $this->createMock(TableSchemaColumnsCache::class);
|
||||
$this->filterQueryBuilder = $this->createMock(FilterQueryBuilderInterface::class);
|
||||
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function testGetType(): void
|
||||
{
|
||||
$type = 'type';
|
||||
$this->contactSegmentFilterCrate = new ContactSegmentFilterCrate(['type' => $type]);
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
self::assertEquals($type, $filter->getType());
|
||||
}
|
||||
|
||||
public function testGetParameterValue(): void
|
||||
{
|
||||
$value = 'value';
|
||||
|
||||
$this->filterDecorator->expects(self::once())
|
||||
->method('getParameterValue')
|
||||
->with($this->contactSegmentFilterCrate)
|
||||
->willReturn($value);
|
||||
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
self::assertEquals($value, $filter->getParameterValue());
|
||||
}
|
||||
|
||||
public function testGetTable(): void
|
||||
{
|
||||
$table = 'table';
|
||||
|
||||
$this->filterDecorator->expects(self::once())
|
||||
->method('getTable')
|
||||
->with($this->contactSegmentFilterCrate)
|
||||
->willReturn($table);
|
||||
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
self::assertEquals($table, $filter->getTable());
|
||||
}
|
||||
|
||||
public function testIsColumnTypeBoolean(): void
|
||||
{
|
||||
$this->contactSegmentFilterCrate = new ContactSegmentFilterCrate(['type' => 'boolean']);
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
self::assertTrue($filter->isColumnTypeBoolean());
|
||||
|
||||
$this->contactSegmentFilterCrate = new ContactSegmentFilterCrate(['type' => 'something']);
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
self::assertFalse($filter->isColumnTypeBoolean());
|
||||
}
|
||||
|
||||
public function testGetFilterQueryBuilder(): void
|
||||
{
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
$this->assertEquals($this->filterQueryBuilder, $filter->getFilterQueryBuilder());
|
||||
}
|
||||
|
||||
public function testGetDoNotContactParts(): void
|
||||
{
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
$parts = $filter->getDoNotContactParts();
|
||||
|
||||
self::assertEquals('email', $parts->getChannel());
|
||||
self::assertEquals(1, $parts->getParameterType());
|
||||
}
|
||||
|
||||
public function testGetParameterHolder(): void
|
||||
{
|
||||
$argument = 'argument';
|
||||
$expectedResult = 'expectedResult';
|
||||
|
||||
$this->filterDecorator->expects(self::once())
|
||||
->method('getParameterHolder')
|
||||
->with($this->contactSegmentFilterCrate, $argument)
|
||||
->willReturn($expectedResult);
|
||||
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
self::assertEquals($expectedResult, $filter->getParameterHolder($argument));
|
||||
}
|
||||
|
||||
public function testGetWhere(): void
|
||||
{
|
||||
$where = 'where';
|
||||
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
$this->filterDecorator->expects(self::once())
|
||||
->method('getWhere')
|
||||
->with($this->contactSegmentFilterCrate)
|
||||
->willReturn($where);
|
||||
|
||||
self::assertEquals($where, $filter->getWhere());
|
||||
}
|
||||
|
||||
public function testIsContactSegmentReference(): void
|
||||
{
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
$matcher = $this->exactly(2);
|
||||
|
||||
$this->filterDecorator->expects($matcher)->method('getField')->willReturnCallback(function (...$parameters) use ($matcher) {
|
||||
if (1 === $matcher->numberOfInvocations()) {
|
||||
$this->assertSame($this->contactSegmentFilterCrate, $parameters[0]);
|
||||
|
||||
return 'leadlist';
|
||||
}
|
||||
if (2 === $matcher->numberOfInvocations()) {
|
||||
$this->assertSame($this->contactSegmentFilterCrate, $parameters[0]);
|
||||
|
||||
return 'something';
|
||||
}
|
||||
});
|
||||
|
||||
self::assertTrue($filter->isContactSegmentReference());
|
||||
self::assertFalse($filter->isContactSegmentReference());
|
||||
}
|
||||
|
||||
public function testGetGlue(): void
|
||||
{
|
||||
$glue = 'glue';
|
||||
|
||||
$this->contactSegmentFilterCrate = new ContactSegmentFilterCrate(['glue' => $glue]);
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
self::assertSame($glue, $filter->getGlue());
|
||||
}
|
||||
|
||||
public function testGetIntegrationCampaignParts(): void
|
||||
{
|
||||
$value = 'value';
|
||||
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
$this->filterDecorator->expects(self::once())
|
||||
->method('getParameterValue')
|
||||
->with($this->contactSegmentFilterCrate)
|
||||
->willReturn($value);
|
||||
|
||||
$parts = $filter->getIntegrationCampaignParts();
|
||||
|
||||
self::assertEquals($value, $parts->getCampaignId());
|
||||
}
|
||||
|
||||
public function testApplyQuery(): void
|
||||
{
|
||||
$queryBuilder = new QueryBuilder($this->createMock(\Doctrine\DBAL\Connection::class));
|
||||
|
||||
$this->filterQueryBuilder->expects(self::once())
|
||||
->method('applyQuery')
|
||||
->willReturn($queryBuilder);
|
||||
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
self::assertSame($queryBuilder, $filter->applyQuery($queryBuilder));
|
||||
}
|
||||
|
||||
public function testGetRelationJoinTable(): void
|
||||
{
|
||||
$table = 'table';
|
||||
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
self::assertNull($filter->getRelationJoinTable());
|
||||
|
||||
$this->filterDecorator = $this->createMock(CompanyDecorator::class);
|
||||
$this->filterDecorator->expects(self::once())
|
||||
->method('getRelationJoinTable')
|
||||
->willReturn($table);
|
||||
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
self::assertEquals($table, $filter->getRelationJoinTable());
|
||||
}
|
||||
|
||||
public function testGetQueryType(): void
|
||||
{
|
||||
$type = 'type';
|
||||
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
$this->filterDecorator->expects(self::once())
|
||||
->method('getQueryType')
|
||||
->willReturn($type);
|
||||
|
||||
self::assertSame($type, $filter->getQueryType());
|
||||
}
|
||||
|
||||
public function testGetNullValue(): void
|
||||
{
|
||||
$value = 'value';
|
||||
|
||||
$this->contactSegmentFilterCrate = new ContactSegmentFilterCrate(['null_value' => $value]);
|
||||
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
self::assertSame($value, $filter->getNullValue());
|
||||
}
|
||||
|
||||
public function testGetColumnMissingColumn(): void
|
||||
{
|
||||
$dbName = 'dbName';
|
||||
$tableName = 'tableName';
|
||||
$columns = ['column1', 'column2'];
|
||||
|
||||
$this->tableSchemaColumnCache->expects(self::once())
|
||||
->method('getCurrentDatabaseName')
|
||||
->willReturn($dbName);
|
||||
|
||||
$this->filterDecorator->expects(self::exactly(2))
|
||||
->method('getTable')
|
||||
->with($this->contactSegmentFilterCrate)
|
||||
->willReturn($tableName);
|
||||
|
||||
$this->tableSchemaColumnCache->expects(self::once())
|
||||
->method('getColumns')
|
||||
->with($tableName)
|
||||
->willReturn($columns);
|
||||
|
||||
$this->filterDecorator->expects(self::exactly(2))
|
||||
->method('getField')
|
||||
->willReturn('notExistingColumn');
|
||||
|
||||
$this->expectException(FieldNotFoundException::class);
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
$filter->getColumn();
|
||||
}
|
||||
|
||||
public function testGetColumn(): void
|
||||
{
|
||||
$dbName = 'dbName';
|
||||
$tableName = 'tableName';
|
||||
$columns = ['column1' => 'something1', 'column2' => 'something2'];
|
||||
|
||||
$this->tableSchemaColumnCache->expects(self::once())
|
||||
->method('getCurrentDatabaseName')
|
||||
->willReturn($dbName);
|
||||
|
||||
$this->filterDecorator->expects(self::once())
|
||||
->method('getTable')
|
||||
->with($this->contactSegmentFilterCrate)
|
||||
->willReturn($tableName);
|
||||
|
||||
$this->tableSchemaColumnCache->expects(self::once())
|
||||
->method('getColumns')
|
||||
->with($tableName)
|
||||
->willReturn($columns);
|
||||
|
||||
$this->filterDecorator->expects(self::exactly(2))
|
||||
->method('getField')
|
||||
->willReturn('column1');
|
||||
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
$this->assertEquals('something1', $filter->getColumn());
|
||||
}
|
||||
|
||||
public function testGetField(): void
|
||||
{
|
||||
$field = 'field';
|
||||
|
||||
$this->filterDecorator->expects(self::once())
|
||||
->method('getField')
|
||||
->willReturn($field);
|
||||
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
self::assertSame($field, $filter->getField());
|
||||
}
|
||||
|
||||
public function testGetRelationJoinTableField(): void
|
||||
{
|
||||
$field = 'field';
|
||||
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
self::assertNull($filter->getRelationJoinTableField());
|
||||
|
||||
$this->filterDecorator = $this->createMock(CompanyDecorator::class);
|
||||
$this->filterDecorator->expects(self::once())
|
||||
->method('getRelationJoinTableField')
|
||||
->willReturn($field);
|
||||
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
self::assertEquals($field, $filter->getRelationJoinTableField());
|
||||
}
|
||||
|
||||
public function testGetAggregateFunction(): void
|
||||
{
|
||||
$function = 'function';
|
||||
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
$this->filterDecorator->expects(self::once())
|
||||
->method('getAggregateFunc')
|
||||
->with($this->contactSegmentFilterCrate)
|
||||
->willReturn($function);
|
||||
|
||||
self::assertSame($function, $filter->getAggregateFunction());
|
||||
}
|
||||
|
||||
public function testGetOperator(): void
|
||||
{
|
||||
$operator = 'operator';
|
||||
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
$this->filterDecorator->expects(self::once())
|
||||
->method('getOperator')
|
||||
->with($this->contactSegmentFilterCrate)
|
||||
->willReturn($operator);
|
||||
|
||||
self::assertSame($operator, $filter->getOperator());
|
||||
}
|
||||
|
||||
public function testToString(): void
|
||||
{
|
||||
$table = 'table';
|
||||
$field = 'field';
|
||||
$queryType = 'queryType';
|
||||
$operator = 'operator';
|
||||
$parameterValue = ['parameterValue'];
|
||||
|
||||
$expectedResult = sprintf(
|
||||
'table: %s, %s on %s %s %s',
|
||||
$table,
|
||||
$field,
|
||||
$queryType,
|
||||
$operator,
|
||||
json_encode($parameterValue)
|
||||
);
|
||||
|
||||
$this->filterDecorator->expects(self::once())
|
||||
->method('getTable')
|
||||
->with($this->contactSegmentFilterCrate)
|
||||
->willReturn($table);
|
||||
|
||||
$this->filterDecorator->expects(self::once())
|
||||
->method('getField')
|
||||
->with($this->contactSegmentFilterCrate)
|
||||
->willReturn($field);
|
||||
|
||||
$this->filterDecorator->expects(self::once())
|
||||
->method('getQueryType')
|
||||
->willReturn($queryType);
|
||||
|
||||
$this->filterDecorator->expects(self::once())
|
||||
->method('getOperator')
|
||||
->with($this->contactSegmentFilterCrate)
|
||||
->willReturn($operator);
|
||||
|
||||
$this->filterDecorator->expects(self::once())
|
||||
->method('getParameterValue')
|
||||
->with($this->contactSegmentFilterCrate)
|
||||
->willReturn($parameterValue);
|
||||
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
$result = $filter->__toString();
|
||||
self::assertEquals($expectedResult, $result);
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dataDoesColumnSupportEmptyValue')]
|
||||
public function testDoesColumnSupportEmptyValue(string $type, bool $doesColumnSupportEmptyValue): void
|
||||
{
|
||||
$this->contactSegmentFilterCrate = new ContactSegmentFilterCrate(['type' => $type]);
|
||||
$filter = $this->createContactSegmentFilter();
|
||||
|
||||
self::assertEquals($doesColumnSupportEmptyValue, $filter->doesColumnSupportEmptyValue());
|
||||
}
|
||||
|
||||
public function testBatchLimitersAreSetCorrectly(): void
|
||||
{
|
||||
$filter = new ContactSegmentFilter(
|
||||
$this->contactSegmentFilterCrate,
|
||||
$this->filterDecorator,
|
||||
$this->tableSchemaColumnCache,
|
||||
$this->filterQueryBuilder,
|
||||
[
|
||||
'minId' => 1,
|
||||
'maxId' => 1,
|
||||
]
|
||||
);
|
||||
self::assertSame([
|
||||
'minId' => 1,
|
||||
'maxId' => 1,
|
||||
], $filter->getBatchLimiters());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<array<bool|string>>
|
||||
*/
|
||||
public static function dataDoesColumnSupportEmptyValue(): iterable
|
||||
{
|
||||
yield ['boolean', true];
|
||||
yield ['date', false];
|
||||
yield ['datetime', false];
|
||||
yield ['email', true];
|
||||
yield ['html', true];
|
||||
yield ['country', true];
|
||||
yield ['locale', true];
|
||||
yield ['lookup', true];
|
||||
yield ['number', true];
|
||||
yield ['tel', true];
|
||||
yield ['region', true];
|
||||
yield ['select', true];
|
||||
yield ['multiselect', true];
|
||||
yield ['text', true];
|
||||
yield ['textarea', true];
|
||||
yield ['time', true];
|
||||
yield ['timezone', true];
|
||||
yield ['url', true];
|
||||
}
|
||||
|
||||
private function createContactSegmentFilter(): ContactSegmentFilter
|
||||
{
|
||||
return new ContactSegmentFilter(
|
||||
$this->contactSegmentFilterCrate,
|
||||
$this->filterDecorator,
|
||||
$this->tableSchemaColumnCache,
|
||||
$this->filterQueryBuilder
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment;
|
||||
|
||||
use Doctrine\Common\DataFixtures\ReferenceRepository;
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\InstallBundle\InstallFixtures\ORM\LeadFieldData;
|
||||
use Mautic\LeadBundle\Command\UpdateLeadListsCommand;
|
||||
use Mautic\LeadBundle\DataFixtures\ORM\LoadCompanyData;
|
||||
use Mautic\LeadBundle\DataFixtures\ORM\LoadLeadData;
|
||||
use Mautic\LeadBundle\DataFixtures\ORM\LoadLeadListData;
|
||||
use Mautic\LeadBundle\Entity\LeadList;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentService;
|
||||
use Mautic\LeadBundle\Segment\Exception\TableNotFoundException;
|
||||
use Mautic\LeadBundle\Tests\DataFixtures\ORM\LoadClickData;
|
||||
use Mautic\LeadBundle\Tests\DataFixtures\ORM\LoadDncData;
|
||||
use Mautic\LeadBundle\Tests\DataFixtures\ORM\LoadPageHitData;
|
||||
use Mautic\LeadBundle\Tests\DataFixtures\ORM\LoadSegmentsData;
|
||||
use Mautic\LeadBundle\Tests\DataFixtures\ORM\LoadTagData;
|
||||
use Mautic\PageBundle\DataFixtures\ORM\LoadPageCategoryData;
|
||||
use Mautic\UserBundle\DataFixtures\ORM\LoadRoleData;
|
||||
use Mautic\UserBundle\DataFixtures\ORM\LoadUserData;
|
||||
use PHPUnit\Framework\Assert;
|
||||
|
||||
/**
|
||||
* These tests cover same tests like \Mautic\LeadBundle\Tests\Model\ListModelFunctionalTest.
|
||||
*/
|
||||
class ContactSegmentServiceFunctionalTest extends MauticMysqlTestCase
|
||||
{
|
||||
/**
|
||||
* @var ReferenceRepository
|
||||
*/
|
||||
private $fixtures;
|
||||
|
||||
/**
|
||||
* @var ContactSegmentService
|
||||
*/
|
||||
private $contactSegmentService;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->fixtures = $this->loadFixtures(
|
||||
[
|
||||
LoadCompanyData::class,
|
||||
LoadLeadListData::class,
|
||||
LoadLeadData::class,
|
||||
LeadFieldData::class,
|
||||
LoadPageHitData::class,
|
||||
LoadSegmentsData::class,
|
||||
LoadPageCategoryData::class,
|
||||
LoadRoleData::class,
|
||||
LoadUserData::class,
|
||||
LoadDncData::class,
|
||||
LoadClickData::class,
|
||||
LoadTagData::class,
|
||||
],
|
||||
false
|
||||
)->getReferenceRepository();
|
||||
|
||||
$this->contactSegmentService = static::getContainer()->get('mautic.lead.model.lead_segment_service');
|
||||
}
|
||||
|
||||
protected function beforeBeginTransaction(): void
|
||||
{
|
||||
$this->resetAutoincrement(
|
||||
[
|
||||
'leads',
|
||||
'lead_lists',
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
public function testSegmentCountIsCorrect(): void
|
||||
{
|
||||
$this->testSymfonyCommand('mautic:segments:update', ['--env' => 'test']);
|
||||
|
||||
// purposively not using dataProvider here to avoid loading fixtures with each segment
|
||||
foreach ($this->provideSegments() as $segmentAlias => $expectedCount) {
|
||||
$reference = $this->getReference($segmentAlias);
|
||||
$segmentContacts = $this->contactSegmentService->getTotalLeadListLeadsCount($reference);
|
||||
Assert::assertEquals(
|
||||
$expectedCount,
|
||||
$segmentContacts[$reference->getId()]['count'],
|
||||
sprintf('There should be %d in segment %s.', $expectedCount, $segmentAlias)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string,int>
|
||||
*/
|
||||
private function provideSegments(): array
|
||||
{
|
||||
return [
|
||||
'segment-test-1' => 1,
|
||||
'segment-test-2' => 4,
|
||||
'segment-test-3' => 24,
|
||||
'segment-test-4' => 1,
|
||||
'segment-test-5' => 53,
|
||||
'like-percent-end' => 32,
|
||||
'segment-test-without-filters' => 0,
|
||||
'segment-test-exclude-segment-with-filters' => 7,
|
||||
'segment-test-include-segment-without-filters' => 0,
|
||||
'segment-test-exclude-segment-without-filters' => 11,
|
||||
'segment-test-include-segment-mixed-filters' => 24,
|
||||
'segment-test-exclude-segment-mixed-filters' => 30,
|
||||
'segment-test-mixed-include-exclude-filters' => 8,
|
||||
'segment-test-manual-membership' => 12,
|
||||
'segment-test-include-segment-manual-members' => 12,
|
||||
'segment-test-exclude-segment-manual-members' => 25,
|
||||
'segment-test-exclude-segment-without-other-filters' => 42,
|
||||
'segment-test-include-segment-with-unrelated-segment-manual-removal' => 11,
|
||||
'segment-membership-regexp' => 11,
|
||||
'segment-company-only-fields' => 6,
|
||||
'segment-including-segment-with-company-only-fields' => 14,
|
||||
'name-is-not-equal-not-null-test' => 54,
|
||||
'manually-unsubscribed-sms-test' => 1,
|
||||
'clicked-link-in-any-email' => 2,
|
||||
'did-not-click-link-in-any-email' => 52,
|
||||
'clicked-link-in-any-email-on-specific-date' => 2,
|
||||
'clicked-link-in-any-sms' => 3,
|
||||
'clicked-link-in-any-sms-on-specific-date' => 2,
|
||||
'tags-empty' => 52,
|
||||
'tags-not-empty' => 2,
|
||||
'segment-having-company' => 50,
|
||||
'segment-not-having-company' => 4,
|
||||
'has-email-and-visited-url' => 4,
|
||||
];
|
||||
}
|
||||
|
||||
public function testSegmentRebuildCommand(): void
|
||||
{
|
||||
// exclude the segment
|
||||
$segmentTest3Ref = $this->getReference('segment-test-3');
|
||||
$lastRebuiltDate = $segmentTest3Ref->getLastBuiltDate();
|
||||
self::assertNull($lastRebuiltDate);
|
||||
|
||||
$this->testSymfonyCommand(
|
||||
UpdateLeadListsCommand::NAME,
|
||||
[
|
||||
'--exclude' => [$segmentTest3Ref->getId()],
|
||||
'--env' => 'test',
|
||||
]
|
||||
);
|
||||
|
||||
self::assertSame($lastRebuiltDate, $segmentTest3Ref->getLastBuiltDate(), 'Make sure the segment was not executed, if excluded.');
|
||||
|
||||
$this->testSymfonyCommand(
|
||||
'mautic:segments:update',
|
||||
[
|
||||
'-i' => $segmentTest3Ref->getId(),
|
||||
'--env' => 'test',
|
||||
]
|
||||
);
|
||||
|
||||
$segmentContacts = $this->contactSegmentService->getTotalLeadListLeadsCount($segmentTest3Ref);
|
||||
|
||||
$this->assertEquals(
|
||||
24,
|
||||
$segmentContacts[$segmentTest3Ref->getId()]['count'],
|
||||
'There should be 24 contacts in the segment-test-3 segment after rebuilding from the command line.'
|
||||
);
|
||||
|
||||
self::assertNotSame($lastRebuiltDate, $segmentTest3Ref->getLastBuiltDate(), 'Make sure the segment was executed, if not excluded.');
|
||||
|
||||
// Remove the title from all contacts, rebuild the list, and check that list is updated
|
||||
$this->em->getConnection()->executeQuery(sprintf('UPDATE %sleads SET title = NULL;', MAUTIC_TABLE_PREFIX));
|
||||
|
||||
$this->testSymfonyCommand(
|
||||
'mautic:segments:update',
|
||||
[
|
||||
'-i' => $segmentTest3Ref->getId(),
|
||||
'--env' => 'test',
|
||||
]
|
||||
);
|
||||
|
||||
$segmentContacts = $this->contactSegmentService->getTotalLeadListLeadsCount($segmentTest3Ref);
|
||||
|
||||
$this->assertEquals(
|
||||
0,
|
||||
$segmentContacts[$segmentTest3Ref->getId()]['count'],
|
||||
'There should be no contacts in the segment-test-3 segment after removing contact titles and rebuilding from the command line.'
|
||||
);
|
||||
|
||||
$segmentTest40Ref = $this->getReference('segment-test-include-segment-with-or');
|
||||
$this->testSymfonyCommand('mautic:segments:update', [
|
||||
'-i' => $segmentTest40Ref->getId(),
|
||||
'--env' => 'test',
|
||||
]);
|
||||
|
||||
$segmentContacts = $this->contactSegmentService->getTotalLeadListLeadsCount($segmentTest40Ref);
|
||||
|
||||
$this->assertEquals(
|
||||
11,
|
||||
$segmentContacts[$segmentTest40Ref->getId()]['count'],
|
||||
'There should be 11 contacts in the segment-test-include-segment-with-or segment after rebuilding from the command line.'
|
||||
);
|
||||
|
||||
$segmentTest51Ref = $this->getReference('has-email-and-visited-url');
|
||||
$this->testSymfonyCommand('mautic:segments:update', [
|
||||
'-i' => $segmentTest51Ref->getId(),
|
||||
'--env' => 'test',
|
||||
]);
|
||||
|
||||
$segmentContacts = $this->contactSegmentService->getTotalLeadListLeadsCount($segmentTest51Ref);
|
||||
|
||||
$this->assertEquals(
|
||||
4,
|
||||
$segmentContacts[$segmentTest51Ref->getId()]['count'],
|
||||
'There should be 4 contacts in the has-email-and-visited-url segment after rebuilding from the command line.'
|
||||
);
|
||||
|
||||
// Change the url from page_hits with the right tracking_id, rebuild the list, and check that list is updated
|
||||
$this->em->getConnection()->executeQuery(sprintf(
|
||||
"UPDATE %spage_hits SET url = '%s' WHERE tracking_id = '%s';",
|
||||
MAUTIC_TABLE_PREFIX,
|
||||
'https://test/regex-segment-other.com',
|
||||
'abcdr')
|
||||
);
|
||||
|
||||
$this->testSymfonyCommand(
|
||||
'mautic:segments:update',
|
||||
[
|
||||
'-i' => $segmentTest51Ref->getId(),
|
||||
'--env' => 'test',
|
||||
]
|
||||
);
|
||||
|
||||
$segmentContacts = $this->contactSegmentService->getTotalLeadListLeadsCount($segmentTest51Ref);
|
||||
|
||||
$this->assertEquals(
|
||||
0,
|
||||
$segmentContacts[$segmentTest51Ref->getId()]['count'],
|
||||
'There should be no contacts in the has-email-and-visited-url segment after removing contact titles and rebuilding from the command line.'
|
||||
);
|
||||
}
|
||||
|
||||
private function getReference(string $name): LeadList
|
||||
{
|
||||
/** @var LeadList $reference */
|
||||
$reference = $this->fixtures->getReference($name);
|
||||
|
||||
return $reference;
|
||||
}
|
||||
|
||||
public function testSegmentRebuildCommandFailsOnMissingTable(): void
|
||||
{
|
||||
/** @var ContactSegmentService $contactSegmentService */
|
||||
$contactSegmentService = $this->getContainer()->get('mautic.lead.model.lead_segment_service');
|
||||
$reference = $this->fixtures->getReference('table-name-missing-in-filter');
|
||||
|
||||
$this->expectException(TableNotFoundException::class);
|
||||
$contactSegmentService->getTotalLeadListLeadsCount($reference);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,367 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator;
|
||||
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterOperator;
|
||||
use Mautic\LeadBundle\Segment\Decorator\BaseDecorator;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(BaseDecorator::class)]
|
||||
class BaseDecoratorTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGetField(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'glue' => 'and',
|
||||
'field' => 'date_identified',
|
||||
'object' => 'lead',
|
||||
'type' => 'datetime',
|
||||
'filter' => null,
|
||||
'display' => null,
|
||||
'operator' => '!empty',
|
||||
]);
|
||||
|
||||
$this->assertSame('date_identified', $baseDecorator->getField($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetTableLead(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'object' => 'lead',
|
||||
]);
|
||||
|
||||
$this->assertSame(MAUTIC_TABLE_PREFIX.'leads', $baseDecorator->getTable($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetTableCompany(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'object' => 'company',
|
||||
]);
|
||||
|
||||
$this->assertSame(MAUTIC_TABLE_PREFIX.'companies', $baseDecorator->getTable($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorEqual(): void
|
||||
{
|
||||
$contactSegmentFilterOperator = $this->createMock(ContactSegmentFilterOperator::class);
|
||||
$contactSegmentFilterOperator->expects($this->once())
|
||||
->method('fixOperator')
|
||||
->with('=')
|
||||
->willReturn('eq');
|
||||
|
||||
$baseDecorator = new BaseDecorator($contactSegmentFilterOperator);
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'operator' => '=',
|
||||
]);
|
||||
|
||||
$this->assertSame('eq', $baseDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorStartsWith(): void
|
||||
{
|
||||
$contactSegmentFilterOperator = $this->createMock(ContactSegmentFilterOperator::class);
|
||||
$contactSegmentFilterOperator->expects($this->once())
|
||||
->method('fixOperator')
|
||||
->with('startsWith')
|
||||
->willReturn('startsWith');
|
||||
|
||||
$baseDecorator = new BaseDecorator($contactSegmentFilterOperator);
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'operator' => 'startsWith',
|
||||
]);
|
||||
|
||||
$this->assertSame('like', $baseDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorEndsWith(): void
|
||||
{
|
||||
$contactSegmentFilterOperator = $this->createMock(ContactSegmentFilterOperator::class);
|
||||
$contactSegmentFilterOperator->expects($this->once())
|
||||
->method('fixOperator')
|
||||
->with('endsWith')
|
||||
->willReturn('endsWith');
|
||||
|
||||
$baseDecorator = new BaseDecorator($contactSegmentFilterOperator);
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'operator' => 'endsWith',
|
||||
]);
|
||||
|
||||
$this->assertSame('like', $baseDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorContainsWith(): void
|
||||
{
|
||||
$contactSegmentFilterOperator = $this->createMock(ContactSegmentFilterOperator::class);
|
||||
$contactSegmentFilterOperator->expects($this->once())
|
||||
->method('fixOperator')
|
||||
->with('contains')
|
||||
->willReturn('contains');
|
||||
|
||||
$baseDecorator = new BaseDecorator($contactSegmentFilterOperator);
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'operator' => 'contains',
|
||||
]);
|
||||
|
||||
$this->assertSame('like', $baseDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetQueryType(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([]);
|
||||
|
||||
$this->assertSame('mautic.lead.query.builder.basic', $baseDecorator->getQueryType($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterHolderSingle(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([]);
|
||||
|
||||
$this->assertSame(':argument', $baseDecorator->getParameterHolder($contactSegmentFilterCrate, 'argument'));
|
||||
}
|
||||
|
||||
public function testGetParameterHolderArray(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([]);
|
||||
|
||||
$argument = [
|
||||
'argument1',
|
||||
'argument2',
|
||||
'argument3',
|
||||
];
|
||||
|
||||
$expected = [
|
||||
':argument1',
|
||||
':argument2',
|
||||
':argument3',
|
||||
];
|
||||
$this->assertSame($expected, $baseDecorator->getParameterHolder($contactSegmentFilterCrate, $argument));
|
||||
}
|
||||
|
||||
public function testGetParameterValueBoolean(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'type' => 'boolean',
|
||||
'filter' => '1',
|
||||
]);
|
||||
|
||||
$this->assertTrue($baseDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'type' => 'boolean',
|
||||
'filter' => '0',
|
||||
]);
|
||||
|
||||
$this->assertFalse($baseDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueNumber(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'type' => 'number',
|
||||
'filter' => '1',
|
||||
]);
|
||||
|
||||
$this->assertSame(1.0, $baseDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueLikeNoPercent(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'type' => 'string',
|
||||
'operator' => 'like',
|
||||
'filter' => 'Test string',
|
||||
]);
|
||||
|
||||
$this->assertSame('%Test string%', $baseDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueNotLike(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'type' => 'string',
|
||||
'operator' => '!like',
|
||||
'filter' => 'Test string',
|
||||
]);
|
||||
|
||||
$this->assertSame('%Test string%', $baseDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueLikeWithOnePercent(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'type' => 'string',
|
||||
'operator' => 'like',
|
||||
'filter' => '%Test string',
|
||||
]);
|
||||
|
||||
$this->assertSame('%Test string', $baseDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueLikeWithTwoPercent(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'type' => 'string',
|
||||
'operator' => 'like',
|
||||
'filter' => '%Test string%',
|
||||
]);
|
||||
|
||||
$this->assertSame('%Test string%', $baseDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueStartsWith(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'type' => 'string',
|
||||
'operator' => 'startsWith',
|
||||
'filter' => 'Test string',
|
||||
]);
|
||||
|
||||
$this->assertSame('Test string%', $baseDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueEndsWith(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'type' => 'string',
|
||||
'operator' => 'endsWith',
|
||||
'filter' => 'Test string',
|
||||
]);
|
||||
|
||||
$this->assertSame('%Test string', $baseDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueContains(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'type' => 'string',
|
||||
'operator' => 'contains',
|
||||
'filter' => 'Test string',
|
||||
]);
|
||||
|
||||
$this->assertSame('%Test string%', $baseDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueContainsShouldNotBeEscaped(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'type' => 'string',
|
||||
'operator' => 'contains',
|
||||
'filter' => 'Test with % and special characters \% should not be escaped %',
|
||||
]);
|
||||
|
||||
$expected = '%Test with % and special characters \% should not be escaped %%';
|
||||
$this->assertSame($expected, $baseDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueRegex(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'type' => 'string',
|
||||
'operator' => 'regexp',
|
||||
'filter' => 'Test \\\s string',
|
||||
]);
|
||||
|
||||
$this->assertSame('Test \s string', $baseDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueNotRegex(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'type' => 'string',
|
||||
'operator' => '!regexp',
|
||||
'filter' => 'Test \\\s string',
|
||||
]);
|
||||
|
||||
$this->assertSame('Test \s string', $baseDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueMultiselect(): void
|
||||
{
|
||||
$baseDecorator = $this->getDecorator();
|
||||
|
||||
$expected = [
|
||||
'(([|]|^)2([|]|$))',
|
||||
'(([|]|^)4([|]|$))',
|
||||
];
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'type' => 'multiselect',
|
||||
'filter' => [2, 4],
|
||||
'operator' => 'in',
|
||||
]);
|
||||
|
||||
$this->assertSame($expected, $baseDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'type' => 'multiselect',
|
||||
'filter' => [2, 4],
|
||||
'operator' => '!in',
|
||||
]);
|
||||
|
||||
$this->assertSame($expected, $baseDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
|
||||
$expected = [
|
||||
'(([|]|^)Value \(1\)([|]|$))',
|
||||
'(([|]|^)Value 2([|]|$))',
|
||||
];
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'type' => 'multiselect',
|
||||
'filter' => ['Value (1)', 'Value 2'],
|
||||
'operator' => 'in',
|
||||
]);
|
||||
|
||||
$this->assertSame($expected, $baseDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BaseDecorator
|
||||
*/
|
||||
private function getDecorator()
|
||||
{
|
||||
$contactSegmentFilterOperator = $this->createMock(ContactSegmentFilterOperator::class);
|
||||
|
||||
return new BaseDecorator($contactSegmentFilterOperator);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator;
|
||||
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterOperator;
|
||||
use Mautic\LeadBundle\Segment\Decorator\CustomMappedDecorator;
|
||||
use Mautic\LeadBundle\Services\ContactSegmentFilterDictionary;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(CustomMappedDecorator::class)]
|
||||
class CustomMappedDecoratorTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGetField(): void
|
||||
{
|
||||
$customMappedDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'field' => 'lead_email_read_count',
|
||||
]);
|
||||
|
||||
$this->assertSame('open_count', $customMappedDecorator->getField($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetTable(): void
|
||||
{
|
||||
$customMappedDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'field' => 'lead_email_read_count',
|
||||
]);
|
||||
|
||||
$this->assertSame(MAUTIC_TABLE_PREFIX.'email_stats', $customMappedDecorator->getTable($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetQueryType(): void
|
||||
{
|
||||
$customMappedDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'field' => 'dnc_bounced',
|
||||
]);
|
||||
|
||||
$this->assertSame('mautic.lead.query.builder.special.dnc', $customMappedDecorator->getQueryType($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetForeignContactColumn(): void
|
||||
{
|
||||
$customMappedDecorator = $this->getDecorator();
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'field' => 'lead_email_read_count',
|
||||
]);
|
||||
|
||||
$this->assertSame('lead_id', $customMappedDecorator->getForeignContactColumn($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return CustomMappedDecorator
|
||||
*/
|
||||
private function getDecorator()
|
||||
{
|
||||
$contactSegmentFilterOperator = $this->createMock(ContactSegmentFilterOperator::class);
|
||||
$dispatcherMock = $this->createMock(EventDispatcherInterface::class);
|
||||
$contactSegmentFilterDictionary = new ContactSegmentFilterDictionary($dispatcherMock);
|
||||
|
||||
return new CustomMappedDecorator($contactSegmentFilterOperator, $contactSegmentFilterDictionary);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,282 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date;
|
||||
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\DateOptionFactory;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Day\DateDayToday;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Day\DateDayTomorrow;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Day\DateDayYesterday;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Month\DateMonthLast;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Month\DateMonthNext;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Month\DateMonthThis;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Other\DateAnniversary;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Other\DateDefault;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Other\DateRelativeInterval;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\TimezoneResolver;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Week\DateWeekLast;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Week\DateWeekNext;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Week\DateWeekThis;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Year\DateYearLast;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Year\DateYearNext;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Year\DateYearThis;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DateDecorator;
|
||||
use Mautic\LeadBundle\Segment\RelativeDate;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(DateOptionFactory::class)]
|
||||
class DateOptionFactoryTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testBirthday(): void
|
||||
{
|
||||
$filterName = 'birthday';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateAnniversary::class, $filterDecorator);
|
||||
|
||||
$filterName = 'anniversary';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateAnniversary::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testDayToday(): void
|
||||
{
|
||||
$filterName = 'today';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateDayToday::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testDayTomorrow(): void
|
||||
{
|
||||
$filterName = 'tomorrow';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateDayTomorrow::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testDayYesterday(): void
|
||||
{
|
||||
$filterName = 'yesterday';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateDayYesterday::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testWeekLast(): void
|
||||
{
|
||||
$filterName = 'last week';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateWeekLast::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testWeekNext(): void
|
||||
{
|
||||
$filterName = 'next week';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateWeekNext::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testWeekThis(): void
|
||||
{
|
||||
$filterName = 'this week';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateWeekThis::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testMonthLast(): void
|
||||
{
|
||||
$filterName = 'last month';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateMonthLast::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testMonthNext(): void
|
||||
{
|
||||
$filterName = 'next month';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateMonthNext::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testMonthThis(): void
|
||||
{
|
||||
$filterName = 'this month';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateMonthThis::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testYearLast(): void
|
||||
{
|
||||
$filterName = 'last year';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateYearLast::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testYearNext(): void
|
||||
{
|
||||
$filterName = 'next year';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateYearNext::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testYearThis(): void
|
||||
{
|
||||
$filterName = 'this year';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateYearThis::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testRelativePlus(): void
|
||||
{
|
||||
$filterName = '+20 days';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateRelativeInterval::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testRelativeMinus(): void
|
||||
{
|
||||
$filterName = '+20 days';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateRelativeInterval::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testRelativeAgo(): void
|
||||
{
|
||||
$filterName = '20 days ago';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateRelativeInterval::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testRelativeFirstDayOf(): void
|
||||
{
|
||||
$filterName = 'first day of previous month';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateRelativeInterval::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testRelativeLastDayOf(): void
|
||||
{
|
||||
$filterName = 'last day of previous month';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateRelativeInterval::class, $filterDecorator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string[][]
|
||||
*/
|
||||
public static function getRelativeDateNotations(): array
|
||||
{
|
||||
return [
|
||||
[DateRelativeInterval::class, 'first day of January 2021'],
|
||||
[DateRelativeInterval::class, 'last day of January 2021'],
|
||||
[DateRelativeInterval::class, '5 days ago'],
|
||||
[DateDefault::class, 'day of January 2021'],
|
||||
];
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('getRelativeDateNotations')]
|
||||
public function testRelativeDateNotations(string $expectedResult, string $filterName): void
|
||||
{
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf($expectedResult, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testDateDefault(): void
|
||||
{
|
||||
$filterName = '2018-01-01';
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateDefault::class, $filterDecorator);
|
||||
}
|
||||
|
||||
public function testNullValue(): void
|
||||
{
|
||||
$filterName = null;
|
||||
|
||||
$filterDecorator = $this->getFilterDecorator($filterName);
|
||||
|
||||
$this->assertInstanceOf(DateDefault::class, $filterDecorator);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $filterName
|
||||
*
|
||||
* @return \Mautic\LeadBundle\Segment\Decorator\FilterDecoratorInterface
|
||||
*/
|
||||
private function getFilterDecorator($filterName)
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$relativeDate = $this->createMock(RelativeDate::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$relativeDate->method('getRelativeDateStrings')
|
||||
->willReturn(
|
||||
[
|
||||
'mautic.lead.list.month_last' => 'last month',
|
||||
'mautic.lead.list.month_next' => 'next month',
|
||||
'mautic.lead.list.month_this' => 'this month',
|
||||
'mautic.lead.list.today' => 'today',
|
||||
'mautic.lead.list.tomorrow' => 'tomorrow',
|
||||
'mautic.lead.list.yesterday' => 'yesterday',
|
||||
'mautic.lead.list.week_last' => 'last week',
|
||||
'mautic.lead.list.week_next' => 'next week',
|
||||
'mautic.lead.list.week_this' => 'this week',
|
||||
'mautic.lead.list.year_last' => 'last year',
|
||||
'mautic.lead.list.year_next' => 'next year',
|
||||
'mautic.lead.list.year_this' => 'this year',
|
||||
'mautic.lead.list.birthday' => 'birthday',
|
||||
'mautic.lead.list.anniversary' => 'anniversary',
|
||||
]
|
||||
);
|
||||
|
||||
$dateOptionFactory = new DateOptionFactory($dateDecorator, $relativeDate, $timezoneResolver);
|
||||
|
||||
$filter = [
|
||||
'glue' => 'and',
|
||||
'type' => 'datetime',
|
||||
'object' => 'lead',
|
||||
'field' => 'date_identified',
|
||||
'operator' => '=',
|
||||
'filter' => $filterName,
|
||||
'display' => null,
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
|
||||
return $dateOptionFactory->getDateOption($contactSegmentFilterCrate);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date\Day;
|
||||
|
||||
use Mautic\CoreBundle\Helper\DateTimeHelper;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\DateOptionParameters;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Day\DateDayToday;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\TimezoneResolver;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DateDecorator;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(DateDayToday::class)]
|
||||
class DateDayTodayTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGetOperatorBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = [
|
||||
'operator' => '=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateDayToday($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('like', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorLessOrEqual(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$dateDecorator->method('getOperator')
|
||||
->with()
|
||||
->willReturn('=<');
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lte',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateDayToday($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('=<', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('2018-03-02', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '!=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateDayToday($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('2018-03-02%', $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dataProviderForOperatorAndType')]
|
||||
public function testGetParameterValueSingle(string $operator, string $type, string $expectedDateValue): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('2018-03-02 08:00:09', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => $operator,
|
||||
'type' => $type,
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateDayToday($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals($expectedDateValue, $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public static function dataProviderForOperatorAndType(): iterable
|
||||
{
|
||||
yield ['lt', 'date', '2018-03-02'];
|
||||
yield ['lte', 'date', '2018-03-02'];
|
||||
yield ['gt', 'date', '2018-03-02'];
|
||||
yield ['gte', 'date', '2018-03-02'];
|
||||
yield ['lt', 'datetime', '2018-03-02 00:00:00'];
|
||||
yield ['lte', 'datetime', '2018-03-02 23:59:59'];
|
||||
yield ['gt', 'datetime', '2018-03-02 23:59:59'];
|
||||
yield ['gte', 'datetime', '2018-03-02 00:00:00'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date\Day;
|
||||
|
||||
use Mautic\CoreBundle\Helper\DateTimeHelper;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\DateOptionParameters;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Day\DateDayTomorrow;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\TimezoneResolver;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DateDecorator;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(DateDayTomorrow::class)]
|
||||
class DateDayTomorrowTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGetOperatorBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = [
|
||||
'operator' => '=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateDayTomorrow($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('like', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorLessOrEqual(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$dateDecorator->method('getOperator')
|
||||
->with()
|
||||
->willReturn('=<');
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lte',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateDayTomorrow($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('=<', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('2018-03-02', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '!=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateDayTomorrow($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('2018-03-03%', $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dataProviderForOperatorAndType')]
|
||||
public function testGetParameterValueSingle(string $operator, string $type, string $expectedDateValue): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('2018-03-02 08:00:09', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => $operator,
|
||||
'type' => $type,
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateDayTomorrow($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals($expectedDateValue, $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public static function dataProviderForOperatorAndType(): iterable
|
||||
{
|
||||
yield ['lt', 'date', '2018-03-03'];
|
||||
yield ['lte', 'date', '2018-03-03'];
|
||||
yield ['gt', 'date', '2018-03-03'];
|
||||
yield ['gte', 'date', '2018-03-03'];
|
||||
yield ['lt', 'datetime', '2018-03-03 00:00:00'];
|
||||
yield ['lte', 'datetime', '2018-03-03 23:59:59'];
|
||||
yield ['gt', 'datetime', '2018-03-03 23:59:59'];
|
||||
yield ['gte', 'datetime', '2018-03-03 00:00:00'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date\Day;
|
||||
|
||||
use Mautic\CoreBundle\Helper\DateTimeHelper;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\DateOptionParameters;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Day\DateDayYesterday;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\TimezoneResolver;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DateDecorator;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(DateDayYesterday::class)]
|
||||
class DateDayYesterdayTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGetOperatorBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = [
|
||||
'operator' => '=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateDayYesterday($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('like', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorLessOrEqual(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$dateDecorator->method('getOperator')
|
||||
->with()
|
||||
->willReturn('=<');
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lte',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateDayYesterday($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('=<', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('2018-03-02', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '!=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateDayYesterday($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('2018-03-01%', $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dataProviderForOperatorAndType')]
|
||||
public function testGetParameterValueSingle(string $operator, string $type, string $expectedDateValue): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('2018-03-02 08:00:09', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => $operator,
|
||||
'type' => $type,
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateDayYesterday($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals($expectedDateValue, $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return mixed[]
|
||||
*/
|
||||
public static function dataProviderForOperatorAndType(): iterable
|
||||
{
|
||||
yield ['lt', 'date', '2018-03-01'];
|
||||
yield ['lte', 'date', '2018-03-01'];
|
||||
yield ['gt', 'date', '2018-03-01'];
|
||||
yield ['gte', 'date', '2018-03-01'];
|
||||
yield ['lt', 'datetime', '2018-03-01 00:00:00'];
|
||||
yield ['lte', 'datetime', '2018-03-01 23:59:59'];
|
||||
yield ['gt', 'datetime', '2018-03-01 23:59:59'];
|
||||
yield ['gte', 'datetime', '2018-03-01 00:00:00'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date\Month;
|
||||
|
||||
use Mautic\CoreBundle\Helper\DateTimeHelper;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\DateOptionParameters;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Month\DateMonthLast;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\TimezoneResolver;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DateDecorator;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(DateMonthLast::class)]
|
||||
class DateMonthLastTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGetOperatorBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = [
|
||||
'operator' => '=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateMonthLast($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('like', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorLessOrEqual(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$dateDecorator->method('getOperator')
|
||||
->with()
|
||||
->willReturn('=<');
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lte',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateMonthLast($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('=<', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '!=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateMonthLast($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('first day of last month');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-%'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueSingle(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lt',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateMonthLast($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('first day of last month');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-d'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date\Month;
|
||||
|
||||
use Mautic\CoreBundle\Helper\DateTimeHelper;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\DateOptionParameters;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Month\DateMonthNext;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\TimezoneResolver;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DateDecorator;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(DateMonthNext::class)]
|
||||
class DateMonthNextTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGetOperatorBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = [
|
||||
'operator' => '=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateMonthNext($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('like', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorLessOrEqual(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$dateDecorator->method('getOperator')
|
||||
->with()
|
||||
->willReturn('=<');
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lte',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateMonthNext($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('=<', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '!=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateMonthNext($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('first day of next month');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-%'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueSingle(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lt',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateMonthNext($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('first day of next month');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-d'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date\Month;
|
||||
|
||||
use Mautic\CoreBundle\Helper\DateTimeHelper;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\DateOptionParameters;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Month\DateMonthThis;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\TimezoneResolver;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DateDecorator;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(DateMonthThis::class)]
|
||||
class DateMonthThisTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGetOperatorBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = [
|
||||
'operator' => '=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateMonthThis($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('like', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorLessOrEqual(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$dateDecorator->method('getOperator')
|
||||
->with()
|
||||
->willReturn('=<');
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lte',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateMonthThis($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('=<', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '!=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateMonthThis($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('first day of this month');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-%'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueSingle(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lt',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateMonthThis($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('first day of this month');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-d'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date\Other;
|
||||
|
||||
use Doctrine\DBAL\Query\Expression\CompositeExpression;
|
||||
use Mautic\CoreBundle\Helper\DateTimeHelper;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\DateOptionParameters;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Other\DateAnniversary;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\TimezoneResolver;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DateDecorator;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(DateAnniversary::class)]
|
||||
class DateAnniversaryTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGetOperator(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = [
|
||||
'operator' => '=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([]);
|
||||
|
||||
$filterDecorator = new DateAnniversary($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('like', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValue(): void
|
||||
{
|
||||
/**
|
||||
* Today in '%-m-d%' format. This matches date and datetime fields.
|
||||
*/
|
||||
$expectedResult = '%'.(new \DateTime('now', new \DateTimeZone('UTC')))->format('-m-d').'%';
|
||||
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with(false)
|
||||
->willReturn(
|
||||
new DateTimeHelper(
|
||||
new \DateTime('midnight today', new \DateTimeZone('UTC')), null, 'UTC')
|
||||
);
|
||||
|
||||
$filter = [
|
||||
'operator' => '=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([]);
|
||||
|
||||
$filterDecorator = new DateAnniversary($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals($expectedResult, $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueWithRelativeDate(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('2018-03-02', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filter = [
|
||||
'filter' => 'birthday +2days',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
|
||||
$filterDecorator = new DateAnniversary($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('%-03-04%', $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetWhereReturnsCompositeExpression(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = ['field' => 'last_active'];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$dateDecorator->expects($this->once())
|
||||
->method('getWhere')
|
||||
->with($contactSegmentFilterCrate)
|
||||
->willReturn(CompositeExpression::and('expr1', 'expr2'));
|
||||
|
||||
$filterDecorator = new DateAnniversary($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
CompositeExpression::class,
|
||||
$filterDecorator->getWhere($contactSegmentFilterCrate)
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetWhereReturnsString(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = ['field' => 'last_active'];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
// Configure to return a string
|
||||
$dateDecorator->expects($this->once())
|
||||
->method('getWhere')
|
||||
->willReturn('WHERE clause');
|
||||
|
||||
$filterDecorator = new DateAnniversary($dateDecorator, $dateOptionParameters);
|
||||
$this->assertSame('WHERE clause', $filterDecorator->getWhere($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetWhereReturnsNull(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = ['field' => 'last_active'];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
// Configure to return null
|
||||
$dateDecorator->expects($this->once())
|
||||
->method('getWhere')
|
||||
->willReturn(null);
|
||||
|
||||
$filterDecorator = new DateAnniversary($dateDecorator, $dateOptionParameters);
|
||||
$this->assertNull($filterDecorator->getWhere($contactSegmentFilterCrate));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date\Other;
|
||||
|
||||
use Doctrine\DBAL\Query\Expression\CompositeExpression;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Other\DateDefault;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DateDecorator;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(DateDefault::class)]
|
||||
class DateDefaultTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGetParameterValue(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([]);
|
||||
|
||||
$filterDecorator = new DateDefault($dateDecorator, '2018-03-02 01:02:03');
|
||||
|
||||
$this->assertEquals('2018-03-02 01:02:03', $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetWhereReturnsCompositeExpression(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$filterCrate = new ContactSegmentFilterCrate(['field' => 'last_active']);
|
||||
|
||||
// Configure DateDecorator mock to return CompositeExpression
|
||||
$dateDecorator->expects($this->once())
|
||||
->method('getWhere')
|
||||
->with($filterCrate)
|
||||
->willReturn(CompositeExpression::and('field = 1', 'field = 2'));
|
||||
|
||||
$filterDecorator = new DateDefault($dateDecorator, '2025-01-01');
|
||||
|
||||
$this->assertInstanceOf(
|
||||
CompositeExpression::class,
|
||||
$filterDecorator->getWhere($filterCrate)
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetWhereReturnsString(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$filterCrate = new ContactSegmentFilterCrate(['field' => 'last_active']);
|
||||
|
||||
// Configure to return string
|
||||
$dateDecorator->expects($this->once())
|
||||
->method('getWhere')
|
||||
->willReturn("date_field > '2025-01-01'");
|
||||
|
||||
$filterDecorator = new DateDefault($dateDecorator, '2025-01-01');
|
||||
|
||||
$this->assertSame(
|
||||
"date_field > '2025-01-01'",
|
||||
$filterDecorator->getWhere($filterCrate)
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetWhereReturnsNull(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$filterCrate = new ContactSegmentFilterCrate(['field' => 'last_active']);
|
||||
|
||||
// Configure to return null
|
||||
$dateDecorator->expects($this->once())
|
||||
->method('getWhere')
|
||||
->willReturn(null);
|
||||
|
||||
$filterDecorator = new DateDefault($dateDecorator, '2025-01-01');
|
||||
|
||||
$this->assertNull($filterDecorator->getWhere($filterCrate));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,231 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date\Other;
|
||||
|
||||
use Doctrine\DBAL\Query\Expression\CompositeExpression;
|
||||
use Mautic\CoreBundle\Helper\DateTimeHelper;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\DateOptionParameters;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Other\DateRelativeInterval;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\TimezoneResolver;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DateDecorator;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(DateRelativeInterval::class)]
|
||||
class DateRelativeIntervalTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGetOperatorEqual(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = [
|
||||
'operator' => '=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateRelativeInterval($dateDecorator, '+5 days', $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('like', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorNotEqual(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = [
|
||||
'operator' => '!=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateRelativeInterval($dateDecorator, '+5 days', $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('notLike', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorLessOrEqual(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$dateDecorator->method('getOperator')
|
||||
->with()
|
||||
->willReturn('==<<'); // Test that value is really returned from Decorator
|
||||
|
||||
$filter = [
|
||||
'operator' => '=<',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateRelativeInterval($dateDecorator, '+5 days', $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('==<<', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValuePlusDaysWithGreaterOperator(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('2018-03-02', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '>',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateRelativeInterval($dateDecorator, '+5 days', $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('2018-03-07', $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueMinusMonthWithNotEqualOperator(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('2018-03-02', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '!=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateRelativeInterval($dateDecorator, '-3 months', $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('2017-12-02%', $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueDaysAgoWithNotEqualOperator(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('2018-03-02', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '!=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateRelativeInterval($dateDecorator, '5 days ago', $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('2018-02-25%', $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueYearsAgoWithGreaterOperator(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('2018-03-02', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '>',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateRelativeInterval($dateDecorator, '2 years ago', $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('2016-03-02', $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueDaysWithEqualOperator(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('2018-03-02', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateRelativeInterval($dateDecorator, '5 days', $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('2018-03-07%', $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetWhereReturnsCompositeExpression(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
$filterCrate = new ContactSegmentFilterCrate(['operator' => '=']);
|
||||
$dateOptionParameters = new DateOptionParameters($filterCrate, [], $timezoneResolver);
|
||||
|
||||
// Mock CompositeExpression return
|
||||
$composite = CompositeExpression::and('field = 1', 'field = 2');
|
||||
$dateDecorator->expects($this->once())
|
||||
->method('getWhere')
|
||||
->with($filterCrate)
|
||||
->willReturn($composite);
|
||||
|
||||
$decorator = new DateRelativeInterval($dateDecorator, '+5 days', $dateOptionParameters);
|
||||
$result = $decorator->getWhere($filterCrate);
|
||||
|
||||
$this->assertInstanceOf(CompositeExpression::class, $result);
|
||||
$this->assertSame($composite, $result);
|
||||
}
|
||||
|
||||
public function testGetWhereReturnsString(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
$filterCrate = new ContactSegmentFilterCrate(['operator' => '=']);
|
||||
$dateOptionParameters = new DateOptionParameters($filterCrate, [], $timezoneResolver);
|
||||
|
||||
// Mock string return
|
||||
$expectedWhere = "date_field > '2023-01-01'";
|
||||
$dateDecorator->expects($this->once())
|
||||
->method('getWhere')
|
||||
->willReturn($expectedWhere);
|
||||
|
||||
$decorator = new DateRelativeInterval($dateDecorator, '+5 days', $dateOptionParameters);
|
||||
$this->assertSame($expectedWhere, $decorator->getWhere($filterCrate));
|
||||
}
|
||||
|
||||
public function testGetWhereReturnsNull(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
$filterCrate = new ContactSegmentFilterCrate(['operator' => '=']);
|
||||
$dateOptionParameters = new DateOptionParameters($filterCrate, [], $timezoneResolver);
|
||||
|
||||
// Mock null return
|
||||
$dateDecorator->expects($this->once())
|
||||
->method('getWhere')
|
||||
->willReturn(null);
|
||||
|
||||
$decorator = new DateRelativeInterval($dateDecorator, '+5 days', $dateOptionParameters);
|
||||
$this->assertNull($decorator->getWhere($filterCrate));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,193 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date;
|
||||
|
||||
use Doctrine\Common\DataFixtures\ReferenceRepository;
|
||||
use Mautic\CoreBundle\Helper\InputHelper;
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\LeadBundle\DataFixtures\ORM\LoadLeadData;
|
||||
use Mautic\LeadBundle\DataFixtures\ORM\LoadLeadListData;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Mautic\LeadBundle\Entity\LeadList;
|
||||
use Mautic\LeadBundle\Entity\LeadRepository;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentService;
|
||||
use Mautic\LeadBundle\Tests\DataFixtures\ORM\LoadSegmentsData;
|
||||
use Mautic\UserBundle\DataFixtures\ORM\LoadRoleData;
|
||||
use Mautic\UserBundle\DataFixtures\ORM\LoadUserData;
|
||||
|
||||
class RelativeDateFunctionalTest extends MauticMysqlTestCase
|
||||
{
|
||||
/**
|
||||
* @var ReferenceRepository
|
||||
*/
|
||||
private $fixtures;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->fixtures = $this->loadFixtures([
|
||||
LoadLeadListData::class,
|
||||
LoadLeadData::class,
|
||||
LoadSegmentsData::class,
|
||||
LoadRoleData::class,
|
||||
LoadUserData::class,
|
||||
], false)->getReferenceRepository();
|
||||
}
|
||||
|
||||
protected function beforeBeginTransaction(): void
|
||||
{
|
||||
$this->resetAutoincrement([
|
||||
'leads',
|
||||
'lead_lists',
|
||||
]);
|
||||
}
|
||||
|
||||
public function testSegmentCountIsCorrectForToday(): void
|
||||
{
|
||||
$name = 'Today';
|
||||
$lead = $this->createLead($name, 'midnight today', '+10 seconds');
|
||||
|
||||
$this->checkSegmentResult($name, $lead);
|
||||
}
|
||||
|
||||
public function testSegmentCountIsCorrectForTomorrow(): void
|
||||
{
|
||||
$name = 'Tomorrow';
|
||||
$lead = $this->createLead($name, 'midnight tomorrow', '+10 seconds');
|
||||
|
||||
$this->checkSegmentResult($name, $lead);
|
||||
}
|
||||
|
||||
public function testSegmentCountIsCorrectForYesterday(): void
|
||||
{
|
||||
$name = 'Yesterday';
|
||||
$lead = $this->createLead($name, 'midnight today', '-10 seconds');
|
||||
|
||||
$this->checkSegmentResult($name, $lead);
|
||||
}
|
||||
|
||||
public function testSegmentCountIsCorrectForWeekLast(): void
|
||||
{
|
||||
$name = 'Last week';
|
||||
$lead = $this->createLead($name, 'midnight monday last week', '+2 days');
|
||||
|
||||
$this->checkSegmentResult($name, $lead);
|
||||
}
|
||||
|
||||
public function testSegmentCountIsCorrectForWeekNext(): void
|
||||
{
|
||||
$name = 'Next week';
|
||||
$lead = $this->createLead($name, 'midnight monday next week', '+2 days');
|
||||
|
||||
$this->checkSegmentResult($name, $lead);
|
||||
}
|
||||
|
||||
public function testSegmentCountIsCorrectForWeekThis(): void
|
||||
{
|
||||
$name = 'This week';
|
||||
$lead = $this->createLead($name, 'midnight monday this week', '+2 days');
|
||||
|
||||
$this->checkSegmentResult($name, $lead);
|
||||
}
|
||||
|
||||
public function testSegmentCountIsCorrectForMonthLast(): void
|
||||
{
|
||||
$name = 'Last month';
|
||||
$lead = $this->createLead($name, 'midnight first day of last month', '+2 days');
|
||||
|
||||
$this->checkSegmentResult($name, $lead);
|
||||
}
|
||||
|
||||
public function testSegmentCountIsCorrectForMonthNext(): void
|
||||
{
|
||||
$name = 'Next month';
|
||||
$lead = $this->createLead($name, 'midnight first day of next month', '+2 days');
|
||||
|
||||
$this->checkSegmentResult($name, $lead);
|
||||
}
|
||||
|
||||
public function testSegmentCountIsCorrectForMonthThis(): void
|
||||
{
|
||||
$name = 'This month';
|
||||
$lead = $this->createLead($name, 'midnight first day of this month', '+2 days');
|
||||
|
||||
$this->checkSegmentResult($name, $lead);
|
||||
}
|
||||
|
||||
public function testSegmentCountIsCorrectForYearLast(): void
|
||||
{
|
||||
$name = 'Last year';
|
||||
$lead = $this->createLead($name, 'midnight first day of last year', '+2 days');
|
||||
|
||||
$this->checkSegmentResult($name, $lead);
|
||||
}
|
||||
|
||||
public function testSegmentCountIsCorrectForYearNext(): void
|
||||
{
|
||||
$name = 'Next year';
|
||||
$lead = $this->createLead($name, 'midnight first day of next year', '+2 days');
|
||||
|
||||
$this->checkSegmentResult($name, $lead);
|
||||
}
|
||||
|
||||
public function testSegmentCountIsCorrectForRelativePlus(): void
|
||||
{
|
||||
$name = 'Relative plus';
|
||||
$lead = $this->createLead($name, 'now', '+5 days');
|
||||
|
||||
$this->checkSegmentResult($name, $lead);
|
||||
}
|
||||
|
||||
public function testSegmentCountIsCorrectForRelativeMinus(): void
|
||||
{
|
||||
$name = 'Relative minus';
|
||||
$lead = $this->createLead($name, 'now', '-4 days');
|
||||
|
||||
$this->checkSegmentResult($name, $lead);
|
||||
}
|
||||
|
||||
private function checkSegmentResult(string $name, Lead $lead): void
|
||||
{
|
||||
/** @var ContactSegmentService $contactSegmentService */
|
||||
$contactSegmentService = static::getContainer()->get('mautic.lead.model.lead_segment_service');
|
||||
|
||||
$alias = strtolower(InputHelper::alphanum($name, false, '-'));
|
||||
|
||||
$segmentName = 'segment-with-relative-date-'.$alias;
|
||||
/** @var LeadList $segmentRef */
|
||||
$segmentRef = $this->fixtures->getReference($segmentName);
|
||||
$segmentContacts = $contactSegmentService->getTotalLeadListLeadsCount($segmentRef);
|
||||
|
||||
$this->assertEquals(
|
||||
1,
|
||||
$segmentContacts[$segmentRef->getId()]['count'],
|
||||
'There should be 1 contacts in the '.$segmentName.' segment.'
|
||||
);
|
||||
$this->assertEquals(
|
||||
$lead->getId(),
|
||||
$segmentContacts[$segmentRef->getId()]['maxId'],
|
||||
'MaxId in the '.$segmentName.' segment should be ID of Lead.'
|
||||
);
|
||||
}
|
||||
|
||||
private function createLead(string $name, string $initialTime, string $dateModifier): Lead
|
||||
{
|
||||
/** @var LeadRepository $leadRepository */
|
||||
$leadRepository = static::getContainer()->get('doctrine.orm.default_entity_manager')->getRepository(Lead::class);
|
||||
|
||||
$date = new \DateTime($initialTime, new \DateTimeZone('UTC'));
|
||||
$date->modify($dateModifier);
|
||||
|
||||
$lead = new Lead();
|
||||
$lead->setLastname('Date');
|
||||
$lead->setFirstname($name);
|
||||
$lead->setDateIdentified($date);
|
||||
|
||||
$leadRepository->saveEntity($lead);
|
||||
|
||||
return $lead;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date;
|
||||
|
||||
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\TimezoneResolver;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
final class TimezoneResolverTest extends TestCase
|
||||
{
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dataTimezones')]
|
||||
public function testTimezones(?string $configuredTimezone, string $expectedTimezone): void
|
||||
{
|
||||
$coreParametersHelper = new class($configuredTimezone) extends CoreParametersHelper {
|
||||
public function __construct(private ?string $configuredTimezone)
|
||||
{
|
||||
}
|
||||
|
||||
public function get($name, $default = null)
|
||||
{
|
||||
Assert::assertSame('default_timezone', $name);
|
||||
|
||||
return $this->configuredTimezone;
|
||||
}
|
||||
};
|
||||
|
||||
$timezoneResolver = new TimezoneResolver($coreParametersHelper);
|
||||
Assert::assertSame(
|
||||
$expectedTimezone,
|
||||
$timezoneResolver->getDefaultDate(false)->getDateTime()->getTimezone()->getName()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<string, array<?string>>
|
||||
*/
|
||||
public static function dataTimezones(): iterable
|
||||
{
|
||||
yield 'Default timezone' => [null, 'UTC'];
|
||||
yield 'UTC timezone' => ['UTC', 'UTC'];
|
||||
yield 'Prague timezone' => ['Europe/Prague', 'Europe/Prague'];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date\Week;
|
||||
|
||||
use Mautic\CoreBundle\Helper\DateTimeHelper;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\DateOptionParameters;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\TimezoneResolver;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Week\DateWeekLast;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DateDecorator;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(DateWeekLast::class)]
|
||||
class DateWeekLastTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGetOperatorBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = [
|
||||
'operator' => '=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekLast($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('between', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorLessOrEqual(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
$dateDecorator->method('getOperator')
|
||||
->with()
|
||||
->willReturn('=<');
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lte',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekLast($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('=<', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '!=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekLast($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDateStart = new \DateTime('monday last week');
|
||||
$expectedDateEnd = new \DateTime('sunday last week');
|
||||
|
||||
$this->assertEquals(
|
||||
[
|
||||
$expectedDateStart->format('Y-m-d'),
|
||||
$expectedDateEnd->format('Y-m-d'),
|
||||
],
|
||||
$filterDecorator->getParameterValue($contactSegmentFilterCrate)
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetParameterValueSingle(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lt',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekLast($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('monday last week');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-d'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueforGreaterOperatorIncludesSunday(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => 'gt',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekLast($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('sunday last week');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-d'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueForLessThanOperatorIncludesSunday(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lte',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekLast($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('sunday last week');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-d'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date\Week;
|
||||
|
||||
use Mautic\CoreBundle\Helper\DateTimeHelper;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\DateOptionParameters;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\TimezoneResolver;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Week\DateWeekNext;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DateDecorator;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(\Mautic\LeadBundle\Segment\Decorator\Date\Week\DateWeekLast::class)]
|
||||
class DateWeekNextTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGetOperatorBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = [
|
||||
'operator' => '=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekNext($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('between', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorLessOrEqual(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
$dateDecorator->method('getOperator')
|
||||
->with()
|
||||
->willReturn('=<');
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lte',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekNext($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('=<', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '!=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekNext($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDateStart = new \DateTime('monday next week');
|
||||
$expectedDateEnd = new \DateTime('sunday next week');
|
||||
|
||||
$this->assertEquals(
|
||||
[
|
||||
$expectedDateStart->format('Y-m-d'),
|
||||
$expectedDateEnd->format('Y-m-d'),
|
||||
],
|
||||
$filterDecorator->getParameterValue($contactSegmentFilterCrate)
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetParameterValueSingle(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lt',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekNext($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('monday next week');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-d'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueforGreaterOperatorIncludesSunday(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => 'gt',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekNext($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('sunday next week');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-d'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueForLessThanOperatorIncludesSunday(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lte',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekNext($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('sunday next week');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-d'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,150 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date\Week;
|
||||
|
||||
use Mautic\CoreBundle\Helper\DateTimeHelper;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\DateOptionParameters;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\TimezoneResolver;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Week\DateWeekThis;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DateDecorator;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(\Mautic\LeadBundle\Segment\Decorator\Date\Week\DateWeekLast::class)]
|
||||
class DateWeekThisTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGetOperatorBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = [
|
||||
'operator' => '=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekThis($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('between', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorLessOrEqual(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
$dateDecorator->method('getOperator')
|
||||
->with()
|
||||
->willReturn('=<');
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lte',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekThis($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('=<', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '!=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekThis($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDateStart = new \DateTime('monday this week');
|
||||
$expectedDateEnd = new \DateTime('sunday this week');
|
||||
|
||||
$this->assertEquals(
|
||||
[
|
||||
$expectedDateStart->format('Y-m-d'),
|
||||
$expectedDateEnd->format('Y-m-d'),
|
||||
],
|
||||
$filterDecorator->getParameterValue($contactSegmentFilterCrate)
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetParameterValueSingle(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lt',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekThis($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('monday this week');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-d'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueforGreaterOperatorIncludesSunday(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => 'gt',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekThis($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('sunday this week');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-d'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueForLessThanOperatorIncludesSunday(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lte',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateWeekThis($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('sunday this week');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-d'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date\Year;
|
||||
|
||||
use Mautic\CoreBundle\Helper\DateTimeHelper;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\DateOptionParameters;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\TimezoneResolver;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Year\DateYearLast;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DateDecorator;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(DateYearLast::class)]
|
||||
class DateYearLastTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGetOperatorBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = [
|
||||
'operator' => '=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateYearLast($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('like', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorLessOrEqual(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$dateDecorator->method('getOperator')
|
||||
->with()
|
||||
->willReturn('==<<');
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lte',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateYearLast($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('==<<', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '!=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateYearLast($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('first day of january last year');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-%'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueSingle(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lt',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateYearLast($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('first day of january last year');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-d'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date\Year;
|
||||
|
||||
use Mautic\CoreBundle\Helper\DateTimeHelper;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\DateOptionParameters;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\TimezoneResolver;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Year\DateYearNext;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DateDecorator;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(DateYearNext::class)]
|
||||
class DateYearNextTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGetOperatorBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = [
|
||||
'operator' => '=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateYearNext($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('like', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorLessOrEqual(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$dateDecorator->method('getOperator')
|
||||
->with()
|
||||
->willReturn('==<<');
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lte',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateYearNext($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('==<<', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '!=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateYearNext($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('first day of january next year');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-%'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueSingle(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lt',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateYearNext($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('first day of january next year');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-d'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator\Date\Year;
|
||||
|
||||
use Mautic\CoreBundle\Helper\DateTimeHelper;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\DateOptionParameters;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\TimezoneResolver;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\Year\DateYearThis;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DateDecorator;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(DateYearThis::class)]
|
||||
class DateYearThisTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testGetOperatorBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$filter = [
|
||||
'operator' => '=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateYearThis($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('like', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetOperatorLessOrEqual(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$dateDecorator->method('getOperator')
|
||||
->with()
|
||||
->willReturn('==<<');
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lte',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateYearThis($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$this->assertEquals('==<<', $filterDecorator->getOperator($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueBetween(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => '!=',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateYearThis($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('first day of january this year');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-%'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
|
||||
public function testGetParameterValueSingle(): void
|
||||
{
|
||||
$dateDecorator = $this->createMock(DateDecorator::class);
|
||||
$timezoneResolver = $this->createMock(TimezoneResolver::class);
|
||||
|
||||
$date = new DateTimeHelper('', null, 'local');
|
||||
|
||||
$timezoneResolver->method('getDefaultDate')
|
||||
->with()
|
||||
->willReturn($date);
|
||||
|
||||
$filter = [
|
||||
'operator' => 'lt',
|
||||
];
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate($filter);
|
||||
$dateOptionParameters = new DateOptionParameters($contactSegmentFilterCrate, [], $timezoneResolver);
|
||||
|
||||
$filterDecorator = new DateYearThis($dateDecorator, $dateOptionParameters);
|
||||
|
||||
$expectedDate = new \DateTime('first day of january this year');
|
||||
|
||||
$this->assertEquals($expectedDate->format('Y-m-d'), $filterDecorator->getParameterValue($contactSegmentFilterCrate));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Decorator;
|
||||
|
||||
use Mautic\LeadBundle\Event\LeadListFiltersDecoratorDelegateEvent;
|
||||
use Mautic\LeadBundle\LeadEvents;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\Decorator\BaseDecorator;
|
||||
use Mautic\LeadBundle\Segment\Decorator\CompanyDecorator;
|
||||
use Mautic\LeadBundle\Segment\Decorator\CustomMappedDecorator;
|
||||
use Mautic\LeadBundle\Segment\Decorator\Date\DateOptionFactory;
|
||||
use Mautic\LeadBundle\Segment\Decorator\DecoratorFactory;
|
||||
use Mautic\LeadBundle\Segment\Decorator\FilterDecoratorInterface;
|
||||
use Mautic\LeadBundle\Services\ContactSegmentFilterDictionary;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
class DecoratorFactoryTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
/**
|
||||
* @var MockObject|EventDispatcherInterface
|
||||
*/
|
||||
private MockObject $eventDispatcherMock;
|
||||
|
||||
private ContactSegmentFilterDictionary $contactSegmentFilterDictionary;
|
||||
|
||||
/**
|
||||
* @var MockObject|BaseDecorator
|
||||
*/
|
||||
private MockObject $baseDecorator;
|
||||
|
||||
/**
|
||||
* @var MockObject|CustomMappedDecorator
|
||||
*/
|
||||
private MockObject $customMappedDecorator;
|
||||
|
||||
/**
|
||||
* @var MockObject|CompanyDecorator
|
||||
*/
|
||||
private MockObject $companyDecorator;
|
||||
|
||||
/**
|
||||
* @var MockObject|DateOptionFactory
|
||||
*/
|
||||
private MockObject $dateOptionFactory;
|
||||
|
||||
private DecoratorFactory $decoratorFactory;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->eventDispatcherMock = $this->createMock(EventDispatcherInterface::class);
|
||||
$this->contactSegmentFilterDictionary = new ContactSegmentFilterDictionary($this->eventDispatcherMock);
|
||||
$this->baseDecorator = $this->createMock(BaseDecorator::class);
|
||||
$this->customMappedDecorator = $this->createMock(CustomMappedDecorator::class);
|
||||
$this->companyDecorator = $this->createMock(CompanyDecorator::class);
|
||||
$this->dateOptionFactory = $this->createMock(DateOptionFactory::class);
|
||||
$this->decoratorFactory = new DecoratorFactory(
|
||||
$this->contactSegmentFilterDictionary,
|
||||
$this->baseDecorator,
|
||||
$this->customMappedDecorator,
|
||||
$this->dateOptionFactory,
|
||||
$this->companyDecorator,
|
||||
$this->eventDispatcherMock);
|
||||
}
|
||||
|
||||
public function testBaseDecorator(): void
|
||||
{
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'field' => 'date_identified',
|
||||
'type' => 'number',
|
||||
]);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
BaseDecorator::class,
|
||||
$this->decoratorFactory->getDecoratorForFilter($contactSegmentFilterCrate)
|
||||
);
|
||||
}
|
||||
|
||||
public function testCustomMappedDecorator(): void
|
||||
{
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate([
|
||||
'field' => 'hit_url_count',
|
||||
'type' => 'number',
|
||||
]);
|
||||
|
||||
$this->assertInstanceOf(
|
||||
CustomMappedDecorator::class,
|
||||
$this->decoratorFactory->getDecoratorForFilter($contactSegmentFilterCrate)
|
||||
);
|
||||
}
|
||||
|
||||
public function testDateDecoratorWhenNoSubscriberProvidesDecorator(): void
|
||||
{
|
||||
$filterDecoratorInterface = $this->createMock(FilterDecoratorInterface::class);
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate(['type' => 'date']);
|
||||
|
||||
$this->dateOptionFactory->expects($this->once())
|
||||
->method('getDateOption')
|
||||
->with($contactSegmentFilterCrate)
|
||||
->willReturn($filterDecoratorInterface);
|
||||
|
||||
$this->eventDispatcherMock->expects($this->once())
|
||||
->method('dispatch')
|
||||
->with(
|
||||
$this->callback(
|
||||
function (LeadListFiltersDecoratorDelegateEvent $event) use ($contactSegmentFilterCrate) {
|
||||
$this->assertNull($event->getDecorator());
|
||||
$this->assertSame($contactSegmentFilterCrate, $event->getCrate());
|
||||
|
||||
return true;
|
||||
}
|
||||
),
|
||||
LeadEvents::SEGMENT_ON_DECORATOR_DELEGATE
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
$filterDecoratorInterface,
|
||||
$this->decoratorFactory->getDecoratorForFilter($contactSegmentFilterCrate)
|
||||
);
|
||||
}
|
||||
|
||||
public function testDateDecoratorWhenSubscriberProvidesDecorator(): void
|
||||
{
|
||||
$filterDecoratorInterface = $this->createMock(FilterDecoratorInterface::class);
|
||||
$contactSegmentFilterCrate = new ContactSegmentFilterCrate(['type' => 'date']);
|
||||
|
||||
$this->dateOptionFactory->expects($this->never())
|
||||
->method('getDateOption');
|
||||
|
||||
$this->eventDispatcherMock->expects($this->once())
|
||||
->method('dispatch')
|
||||
->with(
|
||||
$this->callback(
|
||||
function (LeadListFiltersDecoratorDelegateEvent $event) use ($contactSegmentFilterCrate, $filterDecoratorInterface) {
|
||||
$this->assertNull($event->getDecorator());
|
||||
$this->assertSame($contactSegmentFilterCrate, $event->getCrate());
|
||||
|
||||
$event->setDecorator($filterDecoratorInterface);
|
||||
|
||||
return true;
|
||||
}
|
||||
),
|
||||
LeadEvents::SEGMENT_ON_DECORATOR_DELEGATE
|
||||
);
|
||||
|
||||
$this->assertSame(
|
||||
$filterDecoratorInterface,
|
||||
$this->decoratorFactory->getDecoratorForFilter($contactSegmentFilterCrate)
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\DoNotContact;
|
||||
|
||||
use Mautic\LeadBundle\Entity\DoNotContact;
|
||||
use Mautic\LeadBundle\Segment\DoNotContact\DoNotContactParts;
|
||||
|
||||
class DoNotContactPartsTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dataProvider')]
|
||||
public function testParts(string $field, string $channel, int $type): void
|
||||
{
|
||||
$doNotContactParts = new DoNotContactParts($field);
|
||||
$this->assertSame($channel, $doNotContactParts->getChannel());
|
||||
$this->assertSame($type, $doNotContactParts->getParameterType());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<array<string,string|int>>
|
||||
*/
|
||||
public static function dataProvider(): iterable
|
||||
{
|
||||
yield [
|
||||
'field' => 'dnc_bounced',
|
||||
'channel' => 'email',
|
||||
'type' => DoNotContact::BOUNCED,
|
||||
];
|
||||
|
||||
yield [
|
||||
'field' => 'dnc_unsubscribed',
|
||||
'channel' => 'email',
|
||||
'type' => DoNotContact::UNSUBSCRIBED,
|
||||
];
|
||||
|
||||
yield [
|
||||
'field' => 'dnc_manual_email',
|
||||
'channel' => 'email',
|
||||
'type' => DoNotContact::MANUAL,
|
||||
];
|
||||
|
||||
yield [
|
||||
'field' => 'dnc_bounced_sms',
|
||||
'channel' => 'sms',
|
||||
'type' => DoNotContact::BOUNCED,
|
||||
];
|
||||
|
||||
yield [
|
||||
'field' => 'dnc_unsubscribed_sms',
|
||||
'channel' => 'sms',
|
||||
'type' => DoNotContact::UNSUBSCRIBED,
|
||||
];
|
||||
|
||||
yield [
|
||||
'field' => 'dnc_manual_sms',
|
||||
'channel' => 'sms',
|
||||
'type' => DoNotContact::MANUAL,
|
||||
];
|
||||
|
||||
yield [
|
||||
'field' => 'dnc_unsubscribed_sms_manually',
|
||||
'channel' => 'sms',
|
||||
'type' => DoNotContact::MANUAL,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\IntegrationCampaign;
|
||||
|
||||
use Mautic\LeadBundle\Segment\IntegrationCampaign\IntegrationCampaignParts;
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\CoversClass(IntegrationCampaignParts::class)]
|
||||
class IntegrationCampaignPartsTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
public function testConnectwise(): void
|
||||
{
|
||||
$field = 'Connectwise::283';
|
||||
$doNotContactParts = new IntegrationCampaignParts($field);
|
||||
|
||||
$this->assertSame('Connectwise', $doNotContactParts->getIntegrationName());
|
||||
$this->assertSame('283', $doNotContactParts->getCampaignId());
|
||||
}
|
||||
|
||||
public function testSalesforceExplicit(): void
|
||||
{
|
||||
$field = 'Salesforce::22';
|
||||
$doNotContactParts = new IntegrationCampaignParts($field);
|
||||
|
||||
$this->assertSame('Salesforce', $doNotContactParts->getIntegrationName());
|
||||
$this->assertSame('22', $doNotContactParts->getCampaignId());
|
||||
}
|
||||
|
||||
public function testSalesforceDefault(): void
|
||||
{
|
||||
$field = '44';
|
||||
$doNotContactParts = new IntegrationCampaignParts($field);
|
||||
|
||||
$this->assertSame('Salesforce', $doNotContactParts->getIntegrationName());
|
||||
$this->assertSame('44', $doNotContactParts->getCampaignId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Query;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Mautic\CoreBundle\Test\Doctrine\MockedConnectionTrait;
|
||||
use Mautic\LeadBundle\Segment\Query\ContactSegmentQueryBuilder;
|
||||
use Mautic\LeadBundle\Segment\Query\QueryBuilder;
|
||||
use Mautic\LeadBundle\Segment\RandomParameterName;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
|
||||
class ContactSegmentQueryBuilderTest extends TestCase
|
||||
{
|
||||
use MockedConnectionTrait;
|
||||
|
||||
public function testAddNewContactsRestrictions(): void
|
||||
{
|
||||
$queryBuilder = new QueryBuilder($this->createConnection());
|
||||
$queryBuilder->select('1');
|
||||
$queryBuilder->from(MAUTIC_TABLE_PREFIX.'leads', 'l');
|
||||
$queryBuilder->where('NULL');
|
||||
|
||||
$filterQueryBuilder = new ContactSegmentQueryBuilder($this->createMock(EntityManager::class), new RandomParameterName(), new EventDispatcher());
|
||||
|
||||
Assert::assertSame($queryBuilder, $filterQueryBuilder->addNewContactsRestrictions($queryBuilder, 8));
|
||||
Assert::assertSame('SELECT 1 FROM '.MAUTIC_TABLE_PREFIX.'leads l WHERE (NULL) AND (l.id NOT IN (SELECT par0.lead_id FROM '.MAUTIC_TABLE_PREFIX.'lead_lists_leads par0 WHERE par0.leadlist_id = 8))', $queryBuilder->getDebugOutput());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public static function dataAddNewContactsRestrictionsWithBatchLimiters(): iterable
|
||||
{
|
||||
yield [['minId' => 1, 'maxId' => 2], 'par0.lead_id BETWEEN 1 and 2'];
|
||||
yield [['minId' => 1], 'par0.lead_id >= 1'];
|
||||
yield [['maxId' => 2], 'par0.lead_id <= 2'];
|
||||
yield [['lead_id' => 1], 'par0.lead_id = 1'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $batchLimiters
|
||||
*/
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dataAddNewContactsRestrictionsWithBatchLimiters')]
|
||||
public function testAddNewContactsRestrictionsWithBatchLimiters(array $batchLimiters, string $expectedWhereClause): void
|
||||
{
|
||||
$queryBuilder = new QueryBuilder($this->createConnection());
|
||||
$queryBuilder->select('1');
|
||||
$queryBuilder->from(MAUTIC_TABLE_PREFIX.'leads', 'l');
|
||||
$queryBuilder->where('NULL');
|
||||
|
||||
$filterQueryBuilder = new ContactSegmentQueryBuilder($this->createMock(EntityManager::class), new RandomParameterName(), new EventDispatcher());
|
||||
|
||||
Assert::assertSame($queryBuilder, $filterQueryBuilder->addNewContactsRestrictions($queryBuilder, 8, $batchLimiters));
|
||||
Assert::assertSame('SELECT 1 FROM '.MAUTIC_TABLE_PREFIX.'leads l WHERE (NULL) AND (l.id NOT IN (SELECT par0.lead_id FROM '.MAUTIC_TABLE_PREFIX.'lead_lists_leads par0 WHERE (par0.leadlist_id = 8) AND ('.$expectedWhereClause.')))', $queryBuilder->getDebugOutput());
|
||||
}
|
||||
|
||||
private function createConnection(): Connection
|
||||
{
|
||||
return $this->getMockedConnection();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Query\Filter;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Mautic\CoreBundle\Test\Doctrine\MockedConnectionTrait;
|
||||
use Mautic\LeadBundle\Provider\FilterOperatorProviderInterface;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilter;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterOperator;
|
||||
use Mautic\LeadBundle\Segment\Decorator\BaseDecorator;
|
||||
use Mautic\LeadBundle\Segment\Query\Filter\ChannelClickQueryBuilder;
|
||||
use Mautic\LeadBundle\Segment\Query\Filter\FilterQueryBuilderInterface;
|
||||
use Mautic\LeadBundle\Segment\Query\QueryBuilder;
|
||||
use Mautic\LeadBundle\Segment\RandomParameterName;
|
||||
use Mautic\LeadBundle\Segment\TableSchemaColumnsCache;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
|
||||
class ChannelClickQueryBuilderTest extends TestCase
|
||||
{
|
||||
use MockedConnectionTrait;
|
||||
|
||||
/**
|
||||
* @var MockObject|RandomParameterName
|
||||
*/
|
||||
private MockObject $randomParameterMock;
|
||||
|
||||
/**
|
||||
* @var MockObject|EventDispatcherInterface
|
||||
*/
|
||||
private MockObject $dispatcherMock;
|
||||
|
||||
/**
|
||||
* @var Connection|MockObject
|
||||
*/
|
||||
private MockObject $connectionMock;
|
||||
|
||||
private ChannelClickQueryBuilder $queryBuilder;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->randomParameterMock = $this->createMock(RandomParameterName::class);
|
||||
$this->dispatcherMock = $this->createMock(EventDispatcherInterface::class);
|
||||
$this->connectionMock = $this->getMockedConnection();
|
||||
$this->queryBuilder = new ChannelClickQueryBuilder(
|
||||
$this->randomParameterMock,
|
||||
$this->dispatcherMock
|
||||
);
|
||||
|
||||
$this->connectionMock->method('quote')
|
||||
->willReturnArgument(0);
|
||||
}
|
||||
|
||||
public function testGetServiceId(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
'mautic.lead.query.builder.channel_click.value',
|
||||
$this->queryBuilder::getServiceId()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public static function dataApplyQuery(): iterable
|
||||
{
|
||||
yield ['eq', '1', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id NOT IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email))'];
|
||||
yield ['eq', '0', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email))'];
|
||||
yield ['neq', '1', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id NOT IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email))'];
|
||||
yield ['neq', '0', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email))'];
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dataApplyQuery')]
|
||||
public function testApplyQuery(string $operator, string $parameterValue, string $expectedQuery): void
|
||||
{
|
||||
$expectedQuery = str_replace('__PREFIX__', MAUTIC_TABLE_PREFIX, $expectedQuery);
|
||||
$queryBuilder = new QueryBuilder($this->connectionMock);
|
||||
$queryBuilder->select('1');
|
||||
$queryBuilder->from(MAUTIC_TABLE_PREFIX.'leads', 'l');
|
||||
|
||||
$filter = $this->getContactSegmentFilter($operator, $parameterValue);
|
||||
|
||||
$this->randomParameterMock->method('generateRandomParameterName')
|
||||
->willReturnOnConsecutiveCalls('queryAlias', 'para1', 'para2');
|
||||
|
||||
$this->queryBuilder->applyQuery($queryBuilder, $filter);
|
||||
|
||||
Assert::assertSame($expectedQuery, $queryBuilder->getDebugOutput());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public static function dataApplyQueryWithBatchLimitersMinMaxBoth(): iterable
|
||||
{
|
||||
yield [['minId' => 1, 'maxId' => 1], 'eq', '1', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id NOT IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email) AND (para1.lead_id BETWEEN 1 and 1))'];
|
||||
yield [['minId' => 1, 'maxId' => 1], 'eq', '0', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email) AND (para1.lead_id BETWEEN 1 and 1))'];
|
||||
yield [['minId' => 1, 'maxId' => 1], 'neq', '1', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id NOT IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email) AND (para1.lead_id BETWEEN 1 and 1))'];
|
||||
yield [['minId' => 1, 'maxId' => 1], 'neq', '0', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email) AND (para1.lead_id BETWEEN 1 and 1))'];
|
||||
|
||||
yield [['minId' => 1], 'eq', '1', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id NOT IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email) AND (para1.lead_id >= 1))'];
|
||||
yield [['minId' => 1], 'eq', '0', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email) AND (para1.lead_id >= 1))'];
|
||||
yield [['minId' => 1], 'neq', '1', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id NOT IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email) AND (para1.lead_id >= 1))'];
|
||||
yield [['minId' => 1], 'neq', '0', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email) AND (para1.lead_id >= 1))'];
|
||||
|
||||
yield [['maxId' => 1], 'eq', '1', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id NOT IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email) AND (para1.lead_id <= 1))'];
|
||||
yield [['maxId' => 1], 'eq', '0', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email) AND (para1.lead_id <= 1))'];
|
||||
yield [['maxId' => 1], 'neq', '1', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id NOT IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email) AND (para1.lead_id <= 1))'];
|
||||
yield [['maxId' => 1], 'neq', '0', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email) AND (para1.lead_id <= 1))'];
|
||||
|
||||
yield [['lead_id' => 1], 'eq', '1', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id NOT IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email) AND (para1.lead_id = 1))'];
|
||||
yield [['lead_id' => 1], 'eq', '0', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email) AND (para1.lead_id = 1))'];
|
||||
yield [['lead_id' => 1], 'neq', '1', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id NOT IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email) AND (para1.lead_id = 1))'];
|
||||
yield [['lead_id' => 1], 'neq', '0', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT para1.lead_id FROM __PREFIX__page_hits para1 WHERE (para1.redirect_id IS NOT NULL) AND (para1.lead_id IS NOT NULL) AND (para1.source = email) AND (para1.lead_id = 1))'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $batchLimiters
|
||||
*/
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dataApplyQueryWithBatchLimitersMinMaxBoth')]
|
||||
public function testApplyQueryWithBatchLimitersMinMaxBoth(array $batchLimiters, string $operator, string $parameterValue, string $expectedQuery): void
|
||||
{
|
||||
$expectedQuery = str_replace('__PREFIX__', MAUTIC_TABLE_PREFIX, $expectedQuery);
|
||||
$queryBuilder = new QueryBuilder($this->connectionMock);
|
||||
$queryBuilder->select('1');
|
||||
$queryBuilder->from(MAUTIC_TABLE_PREFIX.'leads', 'l');
|
||||
|
||||
$filter = $this->getContactSegmentFilter($operator, $parameterValue, $batchLimiters);
|
||||
|
||||
$this->randomParameterMock->method('generateRandomParameterName')
|
||||
->willReturnOnConsecutiveCalls('queryAlias', 'para1', 'para2');
|
||||
|
||||
$this->queryBuilder->applyQuery($queryBuilder, $filter);
|
||||
|
||||
Assert::assertSame($expectedQuery, $queryBuilder->getDebugOutput());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $batchLimiters
|
||||
*/
|
||||
private function getContactSegmentFilter(string $operator, string $parameterValue, array $batchLimiters = []): ContactSegmentFilter
|
||||
{
|
||||
return new ContactSegmentFilter(
|
||||
new ContactSegmentFilterCrate(
|
||||
[
|
||||
'operator' => $operator,
|
||||
'glue' => 'and',
|
||||
'field' => 'email_id',
|
||||
'object' => 'behaviors',
|
||||
'type' => 'boolean',
|
||||
'properties' => [
|
||||
'filter' => $parameterValue,
|
||||
],
|
||||
]
|
||||
),
|
||||
new BaseDecorator(new ContactSegmentFilterOperator(
|
||||
$this->createMock(FilterOperatorProviderInterface::class)
|
||||
)),
|
||||
new TableSchemaColumnsCache($this->createMock(EntityManager::class)),
|
||||
$this->createMock(FilterQueryBuilderInterface::class),
|
||||
$batchLimiters
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Query\Filter;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Mautic\CoreBundle\Test\Doctrine\MockedConnectionTrait;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilter;
|
||||
use Mautic\LeadBundle\Segment\DoNotContact\DoNotContactParts;
|
||||
use Mautic\LeadBundle\Segment\Query\Filter\DoNotContactFilterQueryBuilder;
|
||||
use Mautic\LeadBundle\Segment\Query\QueryBuilder;
|
||||
use Mautic\LeadBundle\Segment\RandomParameterName;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
|
||||
class DoNotContactFilterQueryBuilderTest extends TestCase
|
||||
{
|
||||
use MockedConnectionTrait;
|
||||
|
||||
public function testGetServiceId(): void
|
||||
{
|
||||
Assert::assertSame('mautic.lead.query.builder.special.dnc', DoNotContactFilterQueryBuilder::getServiceId());
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dataApplyQuery')]
|
||||
public function testApplyQuery(string $operator, string $parameterValue, string $expectedQuery): void
|
||||
{
|
||||
$queryBuilder = new QueryBuilder($this->createConnection());
|
||||
$queryBuilder->select('1');
|
||||
$queryBuilder->from(MAUTIC_TABLE_PREFIX.'leads', 'l');
|
||||
|
||||
$filter = $this->createFilter($operator, $parameterValue);
|
||||
$filterQueryBuilder = new DoNotContactFilterQueryBuilder(new RandomParameterName(), new EventDispatcher());
|
||||
|
||||
$expectedQuery = str_replace('__MAUTIC_TABLE_PREFIX__', MAUTIC_TABLE_PREFIX, $expectedQuery);
|
||||
Assert::assertSame($queryBuilder, $filterQueryBuilder->applyQuery($queryBuilder, $filter));
|
||||
Assert::assertSame($expectedQuery, $queryBuilder->getDebugOutput());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return iterable<array<string>>
|
||||
*/
|
||||
public static function dataApplyQuery(): iterable
|
||||
{
|
||||
yield ['eq', '1', 'SELECT 1 FROM __MAUTIC_TABLE_PREFIX__leads l WHERE l.id IN (SELECT par0.lead_id FROM __MAUTIC_TABLE_PREFIX__lead_donotcontact par0 WHERE (par0.reason = 1) AND (par0.channel = \'email\'))'];
|
||||
yield ['eq', '0', 'SELECT 1 FROM __MAUTIC_TABLE_PREFIX__leads l WHERE l.id NOT IN (SELECT par0.lead_id FROM __MAUTIC_TABLE_PREFIX__lead_donotcontact par0 WHERE (par0.reason = 1) AND (par0.channel = \'email\'))'];
|
||||
yield ['neq', '1', 'SELECT 1 FROM __MAUTIC_TABLE_PREFIX__leads l WHERE l.id NOT IN (SELECT par0.lead_id FROM __MAUTIC_TABLE_PREFIX__lead_donotcontact par0 WHERE (par0.reason = 1) AND (par0.channel = \'email\'))'];
|
||||
yield ['neq', '0', 'SELECT 1 FROM __MAUTIC_TABLE_PREFIX__leads l WHERE l.id IN (SELECT par0.lead_id FROM __MAUTIC_TABLE_PREFIX__lead_donotcontact par0 WHERE (par0.reason = 1) AND (par0.channel = \'email\'))'];
|
||||
}
|
||||
|
||||
private function createConnection(): Connection
|
||||
{
|
||||
return $this->getMockedConnection();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $batchLimiters
|
||||
*/
|
||||
private function createFilter(string $operator, string $parameterValue, array $batchLimiters = []): ContactSegmentFilter
|
||||
{
|
||||
return new class($operator, $parameterValue, $batchLimiters) extends ContactSegmentFilter {
|
||||
/**
|
||||
* @noinspection PhpMissingParentConstructorInspection
|
||||
*/
|
||||
public function __construct(
|
||||
private string $operator,
|
||||
private string $parameterValue,
|
||||
/**
|
||||
* @var array<string, mixed>
|
||||
*/
|
||||
private array $batchLimiters,
|
||||
) {
|
||||
}
|
||||
|
||||
public function getDoNotContactParts(): DoNotContactParts
|
||||
{
|
||||
return new DoNotContactParts('dnc_unsubscribed');
|
||||
}
|
||||
|
||||
public function getOperator(): string
|
||||
{
|
||||
return $this->operator;
|
||||
}
|
||||
|
||||
public function getParameterValue(): string
|
||||
{
|
||||
return $this->parameterValue;
|
||||
}
|
||||
|
||||
public function getGlue(): string
|
||||
{
|
||||
return 'and';
|
||||
}
|
||||
|
||||
public function getBatchLimiters(): array
|
||||
{
|
||||
return $this->batchLimiters;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,276 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Query\Filter;
|
||||
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\ORM\EntityManager;
|
||||
use Mautic\CoreBundle\Test\Doctrine\MockedConnectionTrait;
|
||||
use Mautic\LeadBundle\Provider\FilterOperatorProvider;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilter;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterCrate;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentFilterOperator;
|
||||
use Mautic\LeadBundle\Segment\Decorator\CustomMappedDecorator;
|
||||
use Mautic\LeadBundle\Segment\Query\Filter\ForeignValueFilterQueryBuilder;
|
||||
use Mautic\LeadBundle\Segment\Query\QueryBuilder;
|
||||
use Mautic\LeadBundle\Segment\RandomParameterName;
|
||||
use Mautic\LeadBundle\Segment\TableSchemaColumnsCache;
|
||||
use Mautic\LeadBundle\Services\ContactSegmentFilterDictionary;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class ForeignValueFilterQueryBuilderTest extends TestCase
|
||||
{
|
||||
use MockedConnectionTrait;
|
||||
private RandomParameterName $randomParameter;
|
||||
|
||||
/**
|
||||
* @var EventDispatcherInterface&MockObject
|
||||
*/
|
||||
private MockObject $dispatcher;
|
||||
|
||||
private ForeignValueFilterQueryBuilder $queryBuilder;
|
||||
|
||||
/**
|
||||
* @var Connection&MockObject
|
||||
*/
|
||||
private MockObject $connectionMock;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->randomParameter = new RandomParameterName();
|
||||
$this->dispatcher = $this->createMock(EventDispatcherInterface::class);
|
||||
$this->connectionMock = $this->getMockedConnection();
|
||||
$this->queryBuilder = new ForeignValueFilterQueryBuilder(
|
||||
$this->randomParameter,
|
||||
$this->dispatcher
|
||||
);
|
||||
}
|
||||
|
||||
public function testGetServiceId(): void
|
||||
{
|
||||
$this->assertEquals(
|
||||
'mautic.lead.query.builder.foreign.value',
|
||||
$this->queryBuilder::getServiceId()
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public static function dataApplyQuery(): iterable
|
||||
{
|
||||
yield ['regexp', '.com$', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE par1.url REGEXP '.com$')"];
|
||||
yield ['notRegexp', '.com$', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE par1.url NOT REGEXP '.com$')"];
|
||||
yield ['eq', 'https://acquia.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE par1.url = 'https://acquia.com')"];
|
||||
yield ['neq', 'https://acquia.com', "SELECT 1 FROM __PREFIX__leads l WHERE NOT EXISTS(SELECT NULL FROM __PREFIX__page_hits par1 WHERE (par1.lead_id = l.id) AND ((par1.url = 'https://acquia.com') OR (par1.url IS NULL)))"];
|
||||
yield ['empty', '1', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id NOT IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1)'];
|
||||
yield ['notEmpty', '1', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1)'];
|
||||
yield ['like', '%.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE par1.url LIKE '%.com')"];
|
||||
yield ['notLike', '%.com', "SELECT 1 FROM __PREFIX__leads l WHERE NOT EXISTS(SELECT NULL FROM __PREFIX__page_hits par1 WHERE (par1.lead_id = l.id) AND ((par1.url IS NULL) OR (par1.url LIKE '%.com')))"];
|
||||
yield ['contains', '.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE par1.url LIKE '%.com%')"];
|
||||
yield ['startsWith', 'https://', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE par1.url LIKE 'https://%')"];
|
||||
yield ['endsWith', '.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE par1.url LIKE '%.com')"];
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dataApplyQuery')]
|
||||
public function testApplyQuery(string $operator, string $parameterValue, string $expectedQuery): void
|
||||
{
|
||||
$expectedQuery = str_replace('__PREFIX__', MAUTIC_TABLE_PREFIX, $expectedQuery);
|
||||
$queryBuilder = new QueryBuilder($this->connectionMock);
|
||||
$queryBuilder->select('1');
|
||||
$queryBuilder->from(MAUTIC_TABLE_PREFIX.'leads', 'l');
|
||||
|
||||
$filter = $this->getContactSegmentFilter([
|
||||
'object' => 'behaviors',
|
||||
'glue' => 'and',
|
||||
'field' => 'hit_url',
|
||||
'type' => 'text',
|
||||
'operator' => $operator,
|
||||
'properties' => [
|
||||
'filter' => $parameterValue,
|
||||
],
|
||||
'filter' => null,
|
||||
'display' => null,
|
||||
]);
|
||||
|
||||
$this->queryBuilder->applyQuery($queryBuilder, $filter);
|
||||
|
||||
Assert::assertSame($expectedQuery, $queryBuilder->getDebugOutput());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public static function dataApplyQueryAdditionalFilters(): iterable
|
||||
{
|
||||
yield ['in', [1, 2], 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par2.lead_id FROM __PREFIX__lead_categories par2 WHERE par2.category_id IN (1, 2))'];
|
||||
yield ['notIn', [1, 2], 'SELECT 1 FROM __PREFIX__leads l WHERE NOT EXISTS(SELECT NULL FROM __PREFIX__lead_categories par2 WHERE (par2.lead_id = l.id) AND (par2.category_id IN (1, 2)))'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $parameterValue
|
||||
*/
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dataApplyQueryAdditionalFilters')]
|
||||
public function testApplyQueryAdditionalFilters(string $operator, array $parameterValue, string $expectedQuery): void
|
||||
{
|
||||
$expectedQuery = str_replace('__PREFIX__', MAUTIC_TABLE_PREFIX, $expectedQuery);
|
||||
$queryBuilder = new QueryBuilder($this->connectionMock);
|
||||
$queryBuilder->select('1');
|
||||
$queryBuilder->from(MAUTIC_TABLE_PREFIX.'leads', 'l');
|
||||
|
||||
$filter = $this->getContactSegmentFilter([
|
||||
'glue' => 'and',
|
||||
'field' => 'globalcategory',
|
||||
'object' => 'lead',
|
||||
'type' => 'globalcategory',
|
||||
'operator' => $operator,
|
||||
'properties' => [
|
||||
'filter' => $parameterValue,
|
||||
],
|
||||
]);
|
||||
|
||||
$this->queryBuilder->applyQuery($queryBuilder, $filter);
|
||||
|
||||
Assert::assertSame($expectedQuery, $queryBuilder->getDebugOutput());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public static function dataApplyQueryWithBatchFilters(): iterable
|
||||
{
|
||||
yield [['minId' => 1, 'maxId' => 2], 'regexp', '.com$', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id BETWEEN 1 and 2) AND (par1.url REGEXP '.com$'))"];
|
||||
yield [['minId' => 1], 'regexp', '.com$', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id >= 1) AND (par1.url REGEXP '.com$'))"];
|
||||
yield [['maxId' => 2], 'regexp', '.com$', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id <= 2) AND (par1.url REGEXP '.com$'))"];
|
||||
yield [['lead_id' => 1], 'regexp', '.com$', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id = 1) AND (par1.url REGEXP '.com$'))"];
|
||||
|
||||
yield [['minId' => 1, 'maxId' => 2], 'notRegexp', '.com$', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id BETWEEN 1 and 2) AND (par1.url NOT REGEXP '.com$'))"];
|
||||
yield [['minId' => 1], 'notRegexp', '.com$', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id >= 1) AND (par1.url NOT REGEXP '.com$'))"];
|
||||
yield [['maxId' => 2], 'notRegexp', '.com$', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id <= 2) AND (par1.url NOT REGEXP '.com$'))"];
|
||||
yield [['lead_id' => 1], 'notRegexp', '.com$', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id = 1) AND (par1.url NOT REGEXP '.com$'))"];
|
||||
|
||||
yield [['minId' => 1, 'maxId' => 2], 'eq', 'https://acquia.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id BETWEEN 1 and 2) AND (par1.url = 'https://acquia.com'))"];
|
||||
yield [['minId' => 1], 'eq', 'https://acquia.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id >= 1) AND (par1.url = 'https://acquia.com'))"];
|
||||
yield [['maxId' => 2], 'eq', 'https://acquia.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id <= 2) AND (par1.url = 'https://acquia.com'))"];
|
||||
yield [['lead_id' => 1], 'eq', 'https://acquia.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id = 1) AND (par1.url = 'https://acquia.com'))"]; // yield ['empty', '1', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE par1.url IS NULL)'];
|
||||
|
||||
yield [['minId' => 1, 'maxId' => 2], 'notEmpty', '1', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE par1.lead_id BETWEEN 1 and 2)'];
|
||||
yield [['minId' => 1], 'notEmpty', '1', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE par1.lead_id >= 1)'];
|
||||
yield [['maxId' => 2], 'notEmpty', '1', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE par1.lead_id <= 2)'];
|
||||
yield [['lead_id' => 1], 'notEmpty', '1', 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE par1.lead_id = 1)'];
|
||||
|
||||
yield [['minId' => 1, 'maxId' => 2], 'like', '%.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id BETWEEN 1 and 2) AND (par1.url LIKE '%.com'))"];
|
||||
yield [['minId' => 1], 'like', '%.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id >= 1) AND (par1.url LIKE '%.com'))"];
|
||||
yield [['maxId' => 2], 'like', '%.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id <= 2) AND (par1.url LIKE '%.com'))"];
|
||||
yield [['lead_id' => 1], 'like', '%.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id = 1) AND (par1.url LIKE '%.com'))"];
|
||||
|
||||
yield [['minId' => 1, 'maxId' => 2], 'contains', '.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id BETWEEN 1 and 2) AND (par1.url LIKE '%.com%'))"];
|
||||
yield [['minId' => 1], 'contains', '.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id >= 1) AND (par1.url LIKE '%.com%'))"];
|
||||
yield [['maxId' => 2], 'contains', '.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id <= 2) AND (par1.url LIKE '%.com%'))"];
|
||||
yield [['lead_id' => 1], 'contains', '.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id = 1) AND (par1.url LIKE '%.com%'))"];
|
||||
|
||||
yield [['minId' => 1, 'maxId' => 2], 'startsWith', 'https://', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id BETWEEN 1 and 2) AND (par1.url LIKE 'https://%'))"];
|
||||
yield [['minId' => 1], 'startsWith', 'https://', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id >= 1) AND (par1.url LIKE 'https://%'))"];
|
||||
yield [['maxId' => 2], 'startsWith', 'https://', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id <= 2) AND (par1.url LIKE 'https://%'))"];
|
||||
yield [['lead_id' => 1], 'startsWith', 'https://', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id = 1) AND (par1.url LIKE 'https://%'))"];
|
||||
|
||||
yield [['minId' => 1, 'maxId' => 2], 'endsWith', '.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id BETWEEN 1 and 2) AND (par1.url LIKE '%.com'))"];
|
||||
yield [['minId' => 1], 'endsWith', '.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id >= 1) AND (par1.url LIKE '%.com'))"];
|
||||
yield [['maxId' => 2], 'endsWith', '.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id <= 2) AND (par1.url LIKE '%.com'))"];
|
||||
yield [['lead_id' => 1], 'endsWith', '.com', "SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par1.lead_id FROM __PREFIX__page_hits par1 WHERE (par1.lead_id = 1) AND (par1.url LIKE '%.com'))"];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $batchLimiters
|
||||
*/
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dataApplyQueryWithBatchFilters')]
|
||||
public function testApplyQueryWithBatchFilters(array $batchLimiters, string $operator, string $parameterValue, string $expectedQuery): void
|
||||
{
|
||||
$expectedQuery = str_replace('__PREFIX__', MAUTIC_TABLE_PREFIX, $expectedQuery);
|
||||
$queryBuilder = new QueryBuilder($this->connectionMock);
|
||||
$queryBuilder->select('1');
|
||||
$queryBuilder->from(MAUTIC_TABLE_PREFIX.'leads', 'l');
|
||||
|
||||
$filter = $this->getContactSegmentFilter([
|
||||
'object' => 'behaviors',
|
||||
'glue' => 'and',
|
||||
'field' => 'hit_url',
|
||||
'type' => 'text',
|
||||
'operator' => $operator,
|
||||
'properties' => [
|
||||
'filter' => $parameterValue,
|
||||
],
|
||||
'filter' => null,
|
||||
'display' => null,
|
||||
], $batchLimiters);
|
||||
|
||||
$this->queryBuilder->applyQuery($queryBuilder, $filter);
|
||||
|
||||
Assert::assertSame($expectedQuery, $queryBuilder->getDebugOutput());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<mixed>
|
||||
*/
|
||||
public static function dataApplyQueryAdditionalFiltersWithBatchLimiters(): iterable
|
||||
{
|
||||
yield [['minId' => 1, 'maxId' => 2], 'in', [1, 2], 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par2.lead_id FROM __PREFIX__lead_categories par2 WHERE (par2.lead_id BETWEEN 1 and 2) AND (par2.category_id IN (1, 2)))'];
|
||||
yield [['minId' => 1], 'in', [1, 2], 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par2.lead_id FROM __PREFIX__lead_categories par2 WHERE (par2.lead_id >= 1) AND (par2.category_id IN (1, 2)))'];
|
||||
yield [['maxId' => 2], 'in', [1, 2], 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par2.lead_id FROM __PREFIX__lead_categories par2 WHERE (par2.lead_id <= 2) AND (par2.category_id IN (1, 2)))'];
|
||||
yield [['lead_id' => 1], 'in', [1, 2], 'SELECT 1 FROM __PREFIX__leads l WHERE l.id IN (SELECT par2.lead_id FROM __PREFIX__lead_categories par2 WHERE (par2.lead_id = 1) AND (par2.category_id IN (1, 2)))'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $batchLimiters
|
||||
* @param array<string, mixed> $parameterValue
|
||||
*/
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('dataApplyQueryAdditionalFiltersWithBatchLimiters')]
|
||||
public function testApplyQueryAdditionalFiltersWithBatchLimiters(array $batchLimiters, string $operator, array $parameterValue, string $expectedQuery): void
|
||||
{
|
||||
$expectedQuery = str_replace('__PREFIX__', MAUTIC_TABLE_PREFIX, $expectedQuery);
|
||||
$queryBuilder = new QueryBuilder($this->connectionMock);
|
||||
$queryBuilder->select('1');
|
||||
$queryBuilder->from(MAUTIC_TABLE_PREFIX.'leads', 'l');
|
||||
|
||||
$filter = $this->getContactSegmentFilter([
|
||||
'glue' => 'and',
|
||||
'field' => 'globalcategory',
|
||||
'object' => 'lead',
|
||||
'type' => 'globalcategory',
|
||||
'operator' => $operator,
|
||||
'properties' => [
|
||||
'filter' => $parameterValue,
|
||||
],
|
||||
], $batchLimiters);
|
||||
|
||||
$this->queryBuilder->applyQuery($queryBuilder, $filter);
|
||||
|
||||
Assert::assertSame($expectedQuery, $queryBuilder->getDebugOutput());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $filter
|
||||
* @param array<string, mixed> $batchLimiters
|
||||
*/
|
||||
private function getContactSegmentFilter(array $filter, array $batchLimiters = []): ContactSegmentFilter
|
||||
{
|
||||
return new ContactSegmentFilter(
|
||||
new ContactSegmentFilterCrate($filter),
|
||||
new CustomMappedDecorator(
|
||||
new ContactSegmentFilterOperator(
|
||||
new FilterOperatorProvider($this->dispatcher, $this->createMock(TranslatorInterface::class))
|
||||
),
|
||||
new ContactSegmentFilterDictionary($this->dispatcher)
|
||||
),
|
||||
new TableSchemaColumnsCache($this->createMock(EntityManager::class)),
|
||||
$this->queryBuilder,
|
||||
$batchLimiters
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Query\Filter;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\CoreBundle\Tests\Functional\CreateTestEntitiesTrait;
|
||||
use PHPUnit\Framework\Assert;
|
||||
|
||||
class SegmentReferenceFilterQueryBuilderGlueTest extends MauticMysqlTestCase
|
||||
{
|
||||
use CreateTestEntitiesTrait;
|
||||
|
||||
public function testMultipleFiltersConnectedWithOrGlue(): void
|
||||
{
|
||||
$leadA = $this->createLead('A');
|
||||
$leadB = $this->createLead('B');
|
||||
$leadC = $this->createLead('C');
|
||||
$leadD = $this->createLead('D');
|
||||
|
||||
$segmentA = $this->createSegment('A', []);
|
||||
$this->createListLead($segmentA, $leadA);
|
||||
$this->createListLead($segmentA, $leadD);
|
||||
|
||||
$segmentB = $this->createSegment('B', []);
|
||||
$this->createListLead($segmentB, $leadB);
|
||||
$this->createListLead($segmentB, $leadD);
|
||||
|
||||
$segmentC = $this->createSegment('C', []);
|
||||
$this->createListLead($segmentC, $leadC);
|
||||
$this->createListLead($segmentC, $leadD);
|
||||
|
||||
$this->em->flush();
|
||||
|
||||
$segmentD = $this->createSegment('D', [
|
||||
[
|
||||
'object' => 'lead',
|
||||
'glue' => 'and',
|
||||
'field' => 'leadlist',
|
||||
'type' => 'leadlist',
|
||||
'operator' => 'in',
|
||||
'properties' => [
|
||||
'filter' => [
|
||||
$segmentA->getId(),
|
||||
],
|
||||
],
|
||||
],
|
||||
[
|
||||
'object' => 'lead',
|
||||
'glue' => 'or',
|
||||
'field' => 'leadlist',
|
||||
'type' => 'leadlist',
|
||||
'operator' => 'in',
|
||||
'properties' => [
|
||||
'filter' => [
|
||||
$segmentB->getId(),
|
||||
$segmentC->getId(),
|
||||
],
|
||||
],
|
||||
],
|
||||
]);
|
||||
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$this->testSymfonyCommand('mautic:segments:update', ['--list-id' => $segmentD->getId()]);
|
||||
|
||||
$listModel = static::getContainer()->get('mautic.lead.model.list');
|
||||
|
||||
$leadCount = $listModel->getListLeadRepository()->getContactsCountBySegment($segmentD->getId());
|
||||
Assert::assertSame(4, $leadCount, 'Segment must contain all the leads.');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,513 @@
|
||||
<?php
|
||||
|
||||
/** @noinspection SqlResolve SqlAggregates */
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment\Query;
|
||||
|
||||
use Doctrine\DBAL\ArrayParameterType;
|
||||
use Doctrine\DBAL\Connection;
|
||||
use Doctrine\DBAL\Driver;
|
||||
use Doctrine\DBAL\Platforms\MySQLPlatform;
|
||||
use Mautic\LeadBundle\Segment\Query\Expression\ExpressionBuilder;
|
||||
use Mautic\LeadBundle\Segment\Query\QueryBuilder;
|
||||
use Mautic\LeadBundle\Segment\Query\QueryException;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class QueryBuilderTest extends TestCase
|
||||
{
|
||||
private QueryBuilder $queryBuilder;
|
||||
private Connection $connection;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->connection = $this->createConnectionFake();
|
||||
$this->queryBuilder = new QueryBuilder($this->connection);
|
||||
}
|
||||
|
||||
public function testExpr(): void
|
||||
{
|
||||
$expr = $this->queryBuilder->expr();
|
||||
|
||||
Assert::assertInstanceOf(ExpressionBuilder::class, $expr);
|
||||
Assert::assertSame($expr, $this->queryBuilder->expr());
|
||||
}
|
||||
|
||||
public function testSetParameter(): void
|
||||
{
|
||||
$queryBuilder = $this->queryBuilder->setParameter('one', 'first');
|
||||
Assert::assertSame($queryBuilder, $this->queryBuilder);
|
||||
$this->queryBuilder->setParameter('two', true);
|
||||
$this->queryBuilder->setParameter('three', false);
|
||||
$this->queryBuilder->setParameter(4, 'fourth');
|
||||
|
||||
Assert::assertSame([
|
||||
'one' => 'first',
|
||||
'two' => 1,
|
||||
'three' => 0,
|
||||
4 => 'fourth',
|
||||
], $this->queryBuilder->getParameters());
|
||||
}
|
||||
|
||||
public function testSetQueryPart(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name', 't.enabled')
|
||||
->distinct()
|
||||
->from('table1', 't')
|
||||
->leftJoin('t', 'table2', 'j', 't.id = j.tid')
|
||||
->where('t.enabled = 1');
|
||||
|
||||
$queryBuilder = $this->queryBuilder->setQueryPart('select', 't.name');
|
||||
Assert::assertSame($queryBuilder, $this->queryBuilder);
|
||||
$this->queryBuilder->setQueryPart('where', 't.enabled = 0');
|
||||
$this->queryBuilder->setQueryPart('groupBy', 'j.code');
|
||||
$this->queryBuilder->setQueryPart('distinct', null);
|
||||
|
||||
$this->assertSQL('SELECT t.name FROM table1 t LEFT JOIN table2 j ON t.id = j.tid WHERE t.enabled = 0 GROUP BY j.code');
|
||||
}
|
||||
|
||||
public function testGetSQLSelectSimple(): void
|
||||
{
|
||||
$this->queryBuilder->select('1')
|
||||
->from('table1');
|
||||
$this->assertSQL('SELECT 1 FROM table1', 2);
|
||||
}
|
||||
|
||||
public function testGetSQLSelectComplex(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name')
|
||||
->from('table1', 't')
|
||||
->leftJoin('t', 'table2', 'j', 't.id = j.fid')
|
||||
->where('t.enabled = 1')
|
||||
->groupBy('t.type')
|
||||
->having('t.salary > 5000')
|
||||
->orderBy('t.id', 'DESC')
|
||||
->setFirstResult(30)
|
||||
->setMaxResults(10);
|
||||
$this->assertSQL('SELECT t.name FROM table1 t LEFT JOIN table2 j ON t.id = j.fid WHERE t.enabled = 1 GROUP BY t.type HAVING t.salary > 5000 ORDER BY t.id DESC LIMIT 10 OFFSET 30', 2);
|
||||
}
|
||||
|
||||
public function testGetSQLSelectHint(): void
|
||||
{
|
||||
$this->queryBuilder->select('1')
|
||||
->add('from', [
|
||||
'table' => 'table1',
|
||||
'alias' => 't',
|
||||
'hint' => 'USE INDEX (`PRIMARY`)',
|
||||
], true)
|
||||
->where('t.enabled = 0');
|
||||
$this->assertSQL('SELECT 1 FROM table1 t USE INDEX (`PRIMARY`) WHERE t.enabled = 0', 2);
|
||||
}
|
||||
|
||||
public function testGetSQLInsert(): void
|
||||
{
|
||||
$this->queryBuilder->insert('table1')
|
||||
->values(['name' => 'Jack', 'enabled' => 1]);
|
||||
$this->assertSQL('INSERT INTO table1 (name, enabled) VALUES(Jack, 1)', 2);
|
||||
}
|
||||
|
||||
public function testGetSQLUpdate(): void
|
||||
{
|
||||
$this->queryBuilder->update('table1')
|
||||
->set('enabled', '1')
|
||||
->where('enabled = 0');
|
||||
$this->assertSQL('UPDATE table1 SET enabled = 1 WHERE enabled = 0', 2);
|
||||
}
|
||||
|
||||
public function testGetSQLDelete(): void
|
||||
{
|
||||
$this->queryBuilder->delete('table1')
|
||||
->where('enabled = 1');
|
||||
$this->assertSQL('DELETE FROM table1 WHERE enabled = 1', 2);
|
||||
}
|
||||
|
||||
public function testGetJoinCondition(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name')
|
||||
->from('table1', 'l')
|
||||
->leftJoin('l', 'table2', 'j', 'l.id = j.fid');
|
||||
|
||||
Assert::assertSame('l.id = j.fid', $this->queryBuilder->getJoinCondition('j'));
|
||||
Assert::assertFalse($this->queryBuilder->getJoinCondition('k'));
|
||||
}
|
||||
|
||||
public function testAddJoinCondition(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name')
|
||||
->from('table1', 't')
|
||||
->leftJoin('t', 'table2', 'j', 't.id = j.fid');
|
||||
$this->queryBuilder->addJoinCondition('j', $this->queryBuilder->expr()->eq('j.removed', 1));
|
||||
|
||||
$this->assertSQL('SELECT t.name FROM table1 t LEFT JOIN table2 j ON t.id = j.fid and (j.removed = 1)');
|
||||
}
|
||||
|
||||
public function testAddJoinConditionNonExistentJoin(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name')
|
||||
->from('table1', 't')
|
||||
->leftJoin('t', 'table2', 'j', 't.id = j.fid');
|
||||
|
||||
$this->expectException(QueryException::class);
|
||||
$this->expectExceptionMessage('Inserting condition to nonexistent join x');
|
||||
$this->queryBuilder->addJoinCondition('x', $this->queryBuilder->expr()->eq('j.removed', 1));
|
||||
}
|
||||
|
||||
public function testReplaceJoinCondition(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name')
|
||||
->from('table1', 'l')
|
||||
->leftJoin('l', 'table2', 'j', 'l.id = j.fid');
|
||||
$this->queryBuilder->replaceJoinCondition('j', $this->queryBuilder->expr()->eq('j.removed', 1));
|
||||
|
||||
$this->assertSQL('SELECT t.name FROM table1 l LEFT JOIN table2 j ON j.removed = 1');
|
||||
}
|
||||
|
||||
public function testSetParametersPairsNonArray(): void
|
||||
{
|
||||
$queryBuilder = $this->queryBuilder->setParametersPairs('one', 'first');
|
||||
Assert::assertSame($queryBuilder, $this->queryBuilder);
|
||||
$this->queryBuilder->setParametersPairs('two', 'second');
|
||||
$this->queryBuilder->setParametersPairs('three', 'third');
|
||||
|
||||
Assert::assertSame([
|
||||
'one' => 'first',
|
||||
'two' => 'second',
|
||||
'three' => 'third',
|
||||
], $this->queryBuilder->getParameters());
|
||||
}
|
||||
|
||||
public function testSetParametersPairsWithArray(): void
|
||||
{
|
||||
$queryBuilder = $this->queryBuilder->setParametersPairs(['one', 'three', 'five'], ['first', 'third', 'fifth']);
|
||||
Assert::assertSame($queryBuilder, $this->queryBuilder);
|
||||
Assert::assertSame([
|
||||
'one' => 'first',
|
||||
'three' => 'third',
|
||||
'five' => 'fifth',
|
||||
], $this->queryBuilder->getParameters());
|
||||
}
|
||||
|
||||
public function testGetTableAlias(): void
|
||||
{
|
||||
$this->queryBuilder->select('1')
|
||||
->from('tableFrom', 'f')
|
||||
->leftJoin('f', 'leftJoinTable', 'l', 'f.id = l.fid')
|
||||
->rightJoin('l', 'rightJoinTable', 'r', 'l.id = r.lid')
|
||||
->innerJoin('f', 'innerJoinTable', 'i', 'f.id = i.fid')
|
||||
->where('t.enabled = 1')
|
||||
->groupBy('t.type')
|
||||
->having('t.salary > 5000')
|
||||
->orderBy('t.id', 'DESC')
|
||||
->setFirstResult(30)
|
||||
->setMaxResults(10);
|
||||
|
||||
Assert::assertFalse($this->queryBuilder->getTableAlias('nonExistent'));
|
||||
Assert::assertFalse($this->queryBuilder->getTableAlias('nonExistent', 'inner'));
|
||||
Assert::assertFalse($this->queryBuilder->getTableAlias('nonExistent', 'left'));
|
||||
Assert::assertFalse($this->queryBuilder->getTableAlias('nonExistent', 'right'));
|
||||
|
||||
Assert::assertSame('f', $this->queryBuilder->getTableAlias('tableFrom'));
|
||||
Assert::assertFalse($this->queryBuilder->getTableAlias('tableFrom', 'inner'));
|
||||
Assert::assertFalse($this->queryBuilder->getTableAlias('tableFrom', 'left'));
|
||||
Assert::assertFalse($this->queryBuilder->getTableAlias('tableFrom', 'right'));
|
||||
|
||||
Assert::assertSame('l', $this->queryBuilder->getTableAlias('leftJoinTable'));
|
||||
Assert::assertFalse($this->queryBuilder->getTableAlias('leftJoinTable', 'inner'));
|
||||
Assert::assertSame('l', $this->queryBuilder->getTableAlias('leftJoinTable', 'left'));
|
||||
Assert::assertFalse($this->queryBuilder->getTableAlias('leftJoinTable', 'right'));
|
||||
|
||||
Assert::assertSame('r', $this->queryBuilder->getTableAlias('rightJoinTable'));
|
||||
Assert::assertFalse($this->queryBuilder->getTableAlias('rightJoinTable', 'inner'));
|
||||
Assert::assertFalse($this->queryBuilder->getTableAlias('rightJoinTable', 'left'));
|
||||
Assert::assertSame('r', $this->queryBuilder->getTableAlias('rightJoinTable', 'right'));
|
||||
|
||||
Assert::assertSame('i', $this->queryBuilder->getTableAlias('innerJoinTable'));
|
||||
Assert::assertSame('i', $this->queryBuilder->getTableAlias('innerJoinTable', 'inner'));
|
||||
Assert::assertFalse($this->queryBuilder->getTableAlias('innerJoinTable', 'left'));
|
||||
Assert::assertFalse($this->queryBuilder->getTableAlias('innerJoinTable', 'right'));
|
||||
}
|
||||
|
||||
public function testGetTableJoins(): void
|
||||
{
|
||||
$this->queryBuilder->select('1')
|
||||
->from('tableFrom', 'f')
|
||||
->leftJoin('f', 'leftJoinTable', 'l', 'f.id = l.fid')
|
||||
->rightJoin('l', 'rightJoinTable', 'r', 'l.id = r.lid')
|
||||
->innerJoin('f', 'innerJoinTable', 'i', 'f.id = i.fid')
|
||||
->innerJoin('f', 'innerJoinTable', 'i2', 'f.id = i2.fid')
|
||||
->where('t.enabled = 1')
|
||||
->groupBy('t.type')
|
||||
->having('t.salary > 5000')
|
||||
->orderBy('t.id', 'DESC')
|
||||
->setFirstResult(30)
|
||||
->setMaxResults(10);
|
||||
|
||||
Assert::assertSame([], $this->queryBuilder->getTableJoins('nonExistent'));
|
||||
Assert::assertSame([], $this->queryBuilder->getTableJoins('tableFrom'));
|
||||
Assert::assertSame([
|
||||
[
|
||||
'joinType' => 'left',
|
||||
'joinTable' => 'leftJoinTable',
|
||||
'joinAlias' => 'l',
|
||||
'joinCondition' => 'f.id = l.fid',
|
||||
],
|
||||
], $this->queryBuilder->getTableJoins('leftJoinTable'));
|
||||
Assert::assertSame([
|
||||
[
|
||||
'joinType' => 'right',
|
||||
'joinTable' => 'rightJoinTable',
|
||||
'joinAlias' => 'r',
|
||||
'joinCondition' => 'l.id = r.lid',
|
||||
],
|
||||
], $this->queryBuilder->getTableJoins('rightJoinTable'));
|
||||
Assert::assertSame([
|
||||
[
|
||||
'joinType' => 'inner',
|
||||
'joinTable' => 'innerJoinTable',
|
||||
'joinAlias' => 'i',
|
||||
'joinCondition' => 'f.id = i.fid',
|
||||
],
|
||||
[
|
||||
'joinType' => 'inner',
|
||||
'joinTable' => 'innerJoinTable',
|
||||
'joinAlias' => 'i2',
|
||||
'joinCondition' => 'f.id = i2.fid',
|
||||
],
|
||||
], $this->queryBuilder->getTableJoins('innerJoinTable'));
|
||||
}
|
||||
|
||||
public function testGuessPrimaryLeadContactIdColumnWithOrphanedLeads(): void
|
||||
{
|
||||
$this->queryBuilder->select('1')
|
||||
->from('lead_lists_leads', 'orp');
|
||||
|
||||
Assert::assertSame('orp.lead_id', $this->queryBuilder->guessPrimaryLeadContactIdColumn());
|
||||
}
|
||||
|
||||
public function testGuessPrimaryLeadContactIdColumnWithoutJoins(): void
|
||||
{
|
||||
$this->queryBuilder->select('1')
|
||||
->from('leads', 'l');
|
||||
|
||||
Assert::assertSame('l.id', $this->queryBuilder->guessPrimaryLeadContactIdColumn());
|
||||
}
|
||||
|
||||
public function testGuessPrimaryLeadContactIdColumnWithNonRightJoin(): void
|
||||
{
|
||||
$this->queryBuilder->select('1')
|
||||
->from('leads', 'l')
|
||||
->leftJoin('l', 'leftJoinTable', 'lj', 'l.id = lj.lid')
|
||||
->innerJoin('l', 'innerJoinTable', 'ij', 'l.id = ij.lid');
|
||||
|
||||
Assert::assertSame('l.id', $this->queryBuilder->guessPrimaryLeadContactIdColumn());
|
||||
}
|
||||
|
||||
public function testGuessPrimaryLeadContactIdColumnWithNonMatchingRightJoin(): void
|
||||
{
|
||||
$this->queryBuilder->select('1')
|
||||
->from('leads', 'l')
|
||||
->rightJoin('l', 'rightJoinTable', 'r', 'l.name = r.name');
|
||||
|
||||
Assert::assertSame('l.id', $this->queryBuilder->guessPrimaryLeadContactIdColumn());
|
||||
}
|
||||
|
||||
public function testGuessPrimaryLeadContactIdColumnWithMatchingRightJoin(): void
|
||||
{
|
||||
$this->queryBuilder->select('1')
|
||||
->from('leads', 'l')
|
||||
->rightJoin('l', 'rightJoinTable', 'r', 'l.id = r.lid');
|
||||
|
||||
Assert::assertSame('r.lid', $this->queryBuilder->guessPrimaryLeadContactIdColumn());
|
||||
}
|
||||
|
||||
public function testIsJoinTable(): void
|
||||
{
|
||||
$this->queryBuilder->select('1')
|
||||
->from('leads', 'l')
|
||||
->leftJoin('l', 'leftJoinTable', 'lj', 'l.id = lj.lid')
|
||||
->rightJoin('l', 'rightJoinTable', 'rj', 'l.id = rj.lid')
|
||||
->innerJoin('l', 'innerJoinTable', 'ij', 'l.id = ij.lid');
|
||||
|
||||
Assert::assertFalse($this->queryBuilder->isJoinTable('nonExistent'));
|
||||
Assert::assertFalse($this->queryBuilder->isJoinTable('leads'));
|
||||
Assert::assertTrue($this->queryBuilder->isJoinTable('leftJoinTable'));
|
||||
Assert::assertTrue($this->queryBuilder->isJoinTable('rightJoinTable'));
|
||||
Assert::assertTrue($this->queryBuilder->isJoinTable('innerJoinTable'));
|
||||
}
|
||||
|
||||
public function testGetDebugOutput(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name')
|
||||
->from('table1', 't')
|
||||
->leftJoin('t', 'table2', 'j', 't.id = j.fid')
|
||||
->where('t.enabled = :enabled')
|
||||
->andWhere('t.state IN (:states)')
|
||||
->groupBy('t.type')
|
||||
->having('t.salary > :salary AND t.flag = :flag')
|
||||
->orderBy('t.id', 'DESC')
|
||||
->setParameter('enabled', true)
|
||||
->setParameter('salary', 5000)
|
||||
->setParameter('states', ['new', 'active'], ArrayParameterType::STRING)
|
||||
->setParameter('flag', 'internal')
|
||||
->setFirstResult(30)
|
||||
->setMaxResults(10);
|
||||
|
||||
Assert::assertSame("SELECT t.name FROM table1 t LEFT JOIN table2 j ON t.id = j.fid WHERE (t.enabled = 1) AND (t.state IN ('new', 'active')) GROUP BY t.type HAVING t.salary > 5000 AND t.flag = 'internal' ORDER BY t.id DESC LIMIT 10 OFFSET 30", $this->queryBuilder->getDebugOutput());
|
||||
}
|
||||
|
||||
public function testHasLogicStack(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name')
|
||||
->from('table1', 't')
|
||||
->where('t.enabled = 1');
|
||||
Assert::assertFalse($this->queryBuilder->hasLogicStack());
|
||||
|
||||
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'OR');
|
||||
Assert::assertTrue($this->queryBuilder->hasLogicStack());
|
||||
}
|
||||
|
||||
public function testGetLogicStack(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name')
|
||||
->from('table1', 't')
|
||||
->where('t.enabled = 1');
|
||||
Assert::assertSame([], $this->queryBuilder->getLogicStack());
|
||||
|
||||
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'OR');
|
||||
$this->queryBuilder->addLogic($this->queryBuilder->expr()->lt('a.salary', 3000), 'AND');
|
||||
Assert::assertSame([
|
||||
'a.name = John',
|
||||
'a.salary < 3000',
|
||||
], $this->queryBuilder->getLogicStack());
|
||||
}
|
||||
|
||||
public function testPopLogicStack(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name')
|
||||
->from('table1', 't')
|
||||
->where('t.enabled = 1');
|
||||
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'OR');
|
||||
$this->queryBuilder->addLogic($this->queryBuilder->expr()->lt('a.salary', 3000), 'AND');
|
||||
Assert::assertSame([
|
||||
'a.name = John',
|
||||
'a.salary < 3000',
|
||||
], $this->queryBuilder->popLogicStack());
|
||||
Assert::assertSame([], $this->queryBuilder->getLogicStack());
|
||||
}
|
||||
|
||||
public function testAddLogicOrWithEmptyWhere(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name')
|
||||
->from('table1', 't');
|
||||
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'OR');
|
||||
Assert::assertSame([], $this->queryBuilder->getLogicStack());
|
||||
$this->assertSQL('SELECT t.name FROM table1 t WHERE a.name = John');
|
||||
$this->queryBuilder->applyStackLogic();
|
||||
$this->assertSQL('SELECT t.name FROM table1 t WHERE a.name = John');
|
||||
}
|
||||
|
||||
public function testAddLogicOrWithExistingWhereWithEmptyStack(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name')
|
||||
->from('table1', 't')
|
||||
->where('t.enabled = 1');
|
||||
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'OR');
|
||||
Assert::assertSame(['a.name = John'], $this->queryBuilder->getLogicStack());
|
||||
$this->assertSQL('SELECT t.name FROM table1 t WHERE t.enabled = 1');
|
||||
$this->queryBuilder->applyStackLogic();
|
||||
$this->assertSQL('SELECT t.name FROM table1 t WHERE (t.enabled = 1) OR (a.name = John)');
|
||||
}
|
||||
|
||||
public function testAddLogicOrWithExistingWhereWithExistingStack(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name')
|
||||
->from('table1', 't')
|
||||
->where('t.enabled = 1');
|
||||
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'OR');
|
||||
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.flag', 'active'), 'OR');
|
||||
Assert::assertSame(['a.flag = active'], $this->queryBuilder->getLogicStack());
|
||||
$this->assertSQL('SELECT t.name FROM table1 t WHERE (t.enabled = 1) OR (a.name = John)');
|
||||
$this->queryBuilder->applyStackLogic();
|
||||
$this->assertSQL('SELECT t.name FROM table1 t WHERE (t.enabled = 1) OR (a.name = John) OR (a.flag = active)');
|
||||
}
|
||||
|
||||
public function testAddLogicAndWithEmptyWhere(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name')
|
||||
->from('table1', 't');
|
||||
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'AND');
|
||||
Assert::assertSame([], $this->queryBuilder->getLogicStack());
|
||||
$this->assertSQL('SELECT t.name FROM table1 t WHERE a.name = John');
|
||||
$this->queryBuilder->applyStackLogic();
|
||||
$this->assertSQL('SELECT t.name FROM table1 t WHERE a.name = John');
|
||||
}
|
||||
|
||||
public function testAddLogicAndWithExistingWhereWithEmptyStack(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name')
|
||||
->from('table1', 't')
|
||||
->where('t.enabled = 1');
|
||||
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'AND');
|
||||
Assert::assertSame([], $this->queryBuilder->getLogicStack());
|
||||
$this->assertSQL('SELECT t.name FROM table1 t WHERE (t.enabled = 1) AND (a.name = John)');
|
||||
$this->queryBuilder->applyStackLogic();
|
||||
$this->assertSQL('SELECT t.name FROM table1 t WHERE (t.enabled = 1) AND (a.name = John)');
|
||||
}
|
||||
|
||||
public function testAddLogicAndWithExistingWhereWithExistingStack(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name')
|
||||
->from('table1', 't')
|
||||
->where('t.enabled = 1');
|
||||
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'OR');
|
||||
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.flag', 'active'), 'AND');
|
||||
Assert::assertSame([
|
||||
'a.name = John',
|
||||
'a.flag = active',
|
||||
], $this->queryBuilder->getLogicStack());
|
||||
$this->assertSQL('SELECT t.name FROM table1 t WHERE t.enabled = 1');
|
||||
$this->queryBuilder->applyStackLogic();
|
||||
$this->assertSQL('SELECT t.name FROM table1 t WHERE (t.enabled = 1) OR ((a.name = John) AND (a.flag = active))');
|
||||
}
|
||||
|
||||
public function testApplyStackLogicWithEmptyStack(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name')
|
||||
->from('table1', 't')
|
||||
->where('t.enabled = 1');
|
||||
$queryBuilder = $this->queryBuilder->applyStackLogic();
|
||||
Assert::assertSame($queryBuilder, $this->queryBuilder);
|
||||
$this->assertSQL('SELECT t.name FROM table1 t WHERE t.enabled = 1');
|
||||
}
|
||||
|
||||
public function testApplyStackLogicWithExistingStack(): void
|
||||
{
|
||||
$this->queryBuilder->select('t.name')
|
||||
->from('table1', 't')
|
||||
->where('t.enabled = 1');
|
||||
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.name', 'John'), 'AND');
|
||||
$this->queryBuilder->addLogic($this->queryBuilder->expr()->eq('a.flag', 'active'), 'AND');
|
||||
$queryBuilder = $this->queryBuilder->applyStackLogic();
|
||||
Assert::assertSame($queryBuilder, $this->queryBuilder);
|
||||
$this->assertSQL('SELECT t.name FROM table1 t WHERE (t.enabled = 1) AND (a.name = John) AND (a.flag = active)');
|
||||
}
|
||||
|
||||
private function assertSQL(string $sql, int $repeat = 1): void
|
||||
{
|
||||
for ($i = 0; $i < $repeat; ++$i) {
|
||||
Assert::assertSame($sql, $this->queryBuilder->getSQL());
|
||||
}
|
||||
}
|
||||
|
||||
private function createConnectionFake(): Connection
|
||||
{
|
||||
return new class([], $this->createMock(Driver::class)) extends Connection {
|
||||
public function getDatabasePlatform()
|
||||
{
|
||||
return new MySQLPlatform();
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment;
|
||||
|
||||
use Mautic\LeadBundle\Segment\RandomParameterName;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class RandomParameterNameTest extends TestCase
|
||||
{
|
||||
public function testGenerateRandomParameterName(): void
|
||||
{
|
||||
$generator = new RandomParameterName();
|
||||
|
||||
$expectedValues = [
|
||||
'par0',
|
||||
'par1',
|
||||
'par2',
|
||||
'par3',
|
||||
'par4',
|
||||
'par5',
|
||||
'par6',
|
||||
'par7',
|
||||
'par8',
|
||||
'par9',
|
||||
'para',
|
||||
'parb',
|
||||
'parc',
|
||||
'pard',
|
||||
'pare',
|
||||
'parf',
|
||||
'parg',
|
||||
'parh',
|
||||
'pari',
|
||||
'parj',
|
||||
'park',
|
||||
'parl',
|
||||
'parm',
|
||||
'parn',
|
||||
'paro',
|
||||
'parp',
|
||||
'parq',
|
||||
'parr',
|
||||
'pars',
|
||||
'part',
|
||||
'paru',
|
||||
'parv',
|
||||
'parw',
|
||||
'parx',
|
||||
'pary',
|
||||
'parz',
|
||||
'par10',
|
||||
'par11',
|
||||
];
|
||||
|
||||
foreach ($expectedValues as $expectedValue) {
|
||||
self::assertSame($expectedValue, $generator->generateRandomParameterName());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Mautic\LeadBundle\Tests\Segment;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Mautic\LeadBundle\Entity\LeadField;
|
||||
use Mautic\LeadBundle\Entity\LeadList;
|
||||
use Mautic\LeadBundle\Model\FieldModel;
|
||||
use Mautic\LeadBundle\Segment\ContactSegmentService;
|
||||
|
||||
class SegmentFilterFunctionalTest extends MauticMysqlTestCase
|
||||
{
|
||||
/**
|
||||
* @var Lead[]
|
||||
*/
|
||||
private $leads = [];
|
||||
|
||||
protected $useCleanupRollback = false;
|
||||
|
||||
/**
|
||||
* Test creates: contacts, segment
|
||||
* Test rebuilds segment
|
||||
* Test check that the right contacts are in the segment.
|
||||
*/
|
||||
public function testSegments(): void
|
||||
{
|
||||
$this->createCustomMultiselectField();
|
||||
|
||||
foreach ($this->getSegmentsProvider() as $scenario) {
|
||||
$this->runTestSegments($scenario['contacts'], $scenario['segment']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $contacts
|
||||
* @param mixed[] $segment
|
||||
*/
|
||||
private function runTestSegments(array $contacts, array $segment): void
|
||||
{
|
||||
$countInSegment = $this->createLeads($contacts);
|
||||
$leadList = $this->createSegment($segment);
|
||||
$this->buildSegment($leadList, $countInSegment);
|
||||
$this->cleanAfterTest($leadList);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $contacts
|
||||
*/
|
||||
private function createLeads(array $contacts): int
|
||||
{
|
||||
$countInSegment = 0;
|
||||
foreach ($contacts as $contact) {
|
||||
$lead = $this->createLead($contact);
|
||||
$this->em->persist($lead);
|
||||
$this->leads[] = $lead;
|
||||
if ($contact['in_segment']) {
|
||||
++$countInSegment;
|
||||
}
|
||||
}
|
||||
$this->em->flush();
|
||||
|
||||
return $countInSegment;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $values
|
||||
*/
|
||||
private function createLead(array $values): Lead
|
||||
{
|
||||
$lead = new Lead();
|
||||
foreach ($values as $field => $value) {
|
||||
if ('in_segment' === $field) {
|
||||
continue;
|
||||
}
|
||||
call_user_func_array([$lead, 'set'.$field], [$value]);
|
||||
}
|
||||
|
||||
return $lead;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mixed[] $segmentFilters
|
||||
*/
|
||||
private function createSegment(array $segmentFilters): LeadList
|
||||
{
|
||||
$filters = [];
|
||||
foreach ($segmentFilters as $segmentFilter) {
|
||||
$filters[] = [
|
||||
'object' => 'lead',
|
||||
'glue' => $segmentFilter['glue'],
|
||||
'field' => $segmentFilter['field'],
|
||||
'type' => $segmentFilter['type'],
|
||||
'properties' => ['filter' => $segmentFilter['value']],
|
||||
'operator' => $segmentFilter['operator'],
|
||||
];
|
||||
}
|
||||
|
||||
$payload = [
|
||||
'name' => 'API segment',
|
||||
'alias' => 'api_segment_test',
|
||||
'description' => 'Segment created via API',
|
||||
'filters' => $filters,
|
||||
];
|
||||
|
||||
// Create:
|
||||
$this->client->request('POST', '/api/segments/new', $payload);
|
||||
$clientResponse = $this->client->getResponse();
|
||||
$response = json_decode($clientResponse->getContent(), true);
|
||||
|
||||
if (!empty($response['errors'][0])) {
|
||||
$this->fail($response['errors'][0]['code'].': '.$response['errors'][0]['message']);
|
||||
}
|
||||
|
||||
$segmentId = $response['list']['id'];
|
||||
|
||||
$this->assertSame(201, $clientResponse->getStatusCode());
|
||||
$this->assertGreaterThan(0, $segmentId);
|
||||
|
||||
return $this->em->getRepository(LeadList::class)->find($segmentId);
|
||||
}
|
||||
|
||||
private function buildSegment(LeadList $segment, int $expectedCountInSegment): void
|
||||
{
|
||||
/** @var ContactSegmentService $contactSegmentService */
|
||||
$contactSegmentService = static::getContainer()->get('mautic.lead.model.lead_segment_service');
|
||||
|
||||
$this->testSymfonyCommand('mautic:segments:update', [
|
||||
'-i' => $segment->getId(),
|
||||
'--env' => 'test',
|
||||
]);
|
||||
|
||||
$segmentContacts = $contactSegmentService->getTotalLeadListLeadsCount($segment);
|
||||
$this->assertEquals(
|
||||
$expectedCountInSegment,
|
||||
$segmentContacts[$segment->getId()]['count']
|
||||
);
|
||||
}
|
||||
|
||||
private function cleanAfterTest(LeadList $segment): void
|
||||
{
|
||||
$this->em->remove($segment);
|
||||
foreach ($this->leads as $lead) {
|
||||
$deleteLead = $this->em->getRepository(Lead::class)->find($lead->getId());
|
||||
$this->em->remove($deleteLead);
|
||||
}
|
||||
$this->em->flush();
|
||||
$this->leads = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see self::testSegments
|
||||
*
|
||||
* @return \Generator<int,mixed>
|
||||
*/
|
||||
private function getSegmentsProvider(): \Generator
|
||||
{
|
||||
yield [
|
||||
'contacts' => [
|
||||
['email' => 'lukas@mautic.com', 'in_segment' => true, 'city' => 'Prague'],
|
||||
['email' => 'lukas2@mautic.com', 'in_segment' => true, 'city' => 'Prague 11'],
|
||||
['email' => 'lukas3@mautic.com', 'in_segment' => false, 'city' => 'Praha'],
|
||||
],
|
||||
'segment' => [
|
||||
['field' => 'city', 'operator' => 'startsWith', 'value' => 'Prague', 'glue' => 'and', 'type' => 'text'],
|
||||
],
|
||||
];
|
||||
yield [
|
||||
'contacts' => [
|
||||
['email' => 'lukas@mautic.com', 'in_segment' => true, 'points' => 20],
|
||||
['email' => 'lukas2@mautic.com', 'in_segment' => false, 'points' => 10],
|
||||
['email' => 'lukas3@mautic.com', 'in_segment' => true, 'points' => 25],
|
||||
],
|
||||
'segment' => [
|
||||
['field' => 'points', 'operator' => 'gte', 'value' => 20, 'glue' => 'and', 'type' => 'text'],
|
||||
],
|
||||
];
|
||||
|
||||
yield [
|
||||
'contacts' => [
|
||||
['email' => 'lukas@mautic.com', 'in_segment' => true],
|
||||
],
|
||||
'segment' => [
|
||||
['field' => 'multiselect', 'object' => 'lead', 'operator' => '!in', 'value' => ['s'], 'glue' => 'and', 'type' => 'multiselect'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
protected function createCustomMultiselectField(): void
|
||||
{
|
||||
$field = new LeadField();
|
||||
$field->setType('multiselect');
|
||||
$field->setObject('lead');
|
||||
$field->setAlias('multiselect');
|
||||
$field->setName('Multiselect');
|
||||
$properties = unserialize('a:1:{s:4:"list";a:3:{i:0;a:2:{s:5:"label";s:1:"f";s:5:"value";s:1:"f";}i:1;a:2:{s:5:"label";s:1:"s";s:5:"value";s:1:"s";}i:2;a:2:{s:5:"label";s:1:"t";s:5:"value";s:1:"t";}}}');
|
||||
$field->setProperties($properties);
|
||||
$fieldModel = self::getContainer()->get(FieldModel::class);
|
||||
$fieldModel->saveEntity($field);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user