Initial commit: CloudOps infrastructure platform
This commit is contained in:
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticFocusBundle\Tests\Controller\Api;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
final class FocusApiControllerTest extends MauticMysqlTestCase
|
||||
{
|
||||
/**
|
||||
* @var array<string,mixed>
|
||||
*/
|
||||
private array $testPayload = [
|
||||
'name' => 'test',
|
||||
'type' => 'notice',
|
||||
'website' => 'http://',
|
||||
'style' => 'bar',
|
||||
'htmlMode' => 1,
|
||||
'html' => '<div><strong style="color:red">html mode enabled</strong></div>',
|
||||
'properties' => [
|
||||
'bar' => [
|
||||
'allow_hide' => 1,
|
||||
'sticky' => 1,
|
||||
'size' => 'large',
|
||||
'placement' => 'top',
|
||||
],
|
||||
'modal' => [
|
||||
'placement' => 'top',
|
||||
],
|
||||
'notification' => [
|
||||
'placement' => 'top_left',
|
||||
],
|
||||
'animate' => 1,
|
||||
'link_activation' => 1,
|
||||
'colors' => [
|
||||
'primary' => '27184e',
|
||||
],
|
||||
'content' => [
|
||||
'headline' => '',
|
||||
'font' => 'Arial, Helvetica, sans-serif',
|
||||
],
|
||||
'when' => 'immediately',
|
||||
'frequency' => 'everypage',
|
||||
'stop_after_conversion' => 1,
|
||||
],
|
||||
];
|
||||
|
||||
public function testFocusApiNew(): void
|
||||
{
|
||||
// Create a focus item.
|
||||
$this->client->request(Request::METHOD_POST, '/api/focus/new', $this->testPayload);
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertEquals(Response::HTTP_CREATED, $response->getStatusCode(), $response->getContent());
|
||||
|
||||
$createdItem = json_decode($response->getContent(), true)['focus'];
|
||||
|
||||
Assert::assertNotEmpty($createdItem['id'], $response->getContent());
|
||||
Assert::assertSame($this->testPayload['name'], $createdItem['name'], $response->getContent());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,131 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticFocusBundle\Tests\Controller;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Mautic\PageBundle\Entity\Hit;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\Focus;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\Stat;
|
||||
use MauticPlugin\MauticFocusBundle\Model\FocusModel;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class FocusAjaxControllerFunctionalTest extends MauticMysqlTestCase
|
||||
{
|
||||
public function testViewsCount(): void
|
||||
{
|
||||
/** @var FocusModel $focusModel */
|
||||
$focusModel = static::getContainer()->get('mautic.focus.model.focus');
|
||||
$focus = $this->createFocus('popup');
|
||||
$focusModel->saveEntity($focus);
|
||||
|
||||
$leads = [
|
||||
$this->createLead(),
|
||||
$this->createLead(),
|
||||
];
|
||||
|
||||
$focusModel->addStat($focus, Stat::TYPE_NOTIFICATION, null, $leads[0]);
|
||||
$focusModel->addStat($focus, Stat::TYPE_NOTIFICATION, null, $leads[0]);
|
||||
$focusModel->addStat($focus, Stat::TYPE_NOTIFICATION, null, $leads[1]);
|
||||
|
||||
$this->client->xmlHttpRequest(Request::METHOD_GET, "/s/ajax?action=plugin:focus:getViewsCount&focusId={$focus->getId()}");
|
||||
$response = $this->client->getResponse();
|
||||
$this->assertTrue($response->isOk());
|
||||
$this->assertSame([
|
||||
'success' => 1,
|
||||
'views' => 3,
|
||||
'uniqueViews' => 2,
|
||||
], json_decode($response->getContent(), true));
|
||||
}
|
||||
|
||||
public function testClickThroughCount(): void
|
||||
{
|
||||
/** @var FocusModel $focusModel */
|
||||
$focusModel = static::getContainer()->get('mautic.focus.model.focus');
|
||||
$focus = $this->createFocus('popup');
|
||||
$focusModel->saveEntity($focus);
|
||||
|
||||
$lead1 = $this->createLead();
|
||||
$lead2 = $this->createLead();
|
||||
|
||||
$focusModel->addStat($focus, Stat::TYPE_CLICK, $this->createHit($lead1), $lead1);
|
||||
$focusModel->addStat($focus, Stat::TYPE_CLICK, $this->createHit($lead1), $lead1);
|
||||
$focusModel->addStat($focus, Stat::TYPE_CLICK, $this->createHit($lead2), $lead2);
|
||||
|
||||
$this->client->xmlHttpRequest(Request::METHOD_GET, "/s/ajax?action=plugin:focus:getClickThroughCount&focusId={$focus->getId()}");
|
||||
$response = $this->client->getResponse();
|
||||
$this->assertTrue($response->isOk());
|
||||
$this->assertSame([
|
||||
'success' => 1,
|
||||
'clickThrough' => 2,
|
||||
], json_decode($response->getContent(), true));
|
||||
}
|
||||
|
||||
private function createHit(Lead $lead): Hit
|
||||
{
|
||||
$hit = new Hit();
|
||||
$hit->setLead($lead);
|
||||
|
||||
return $hit;
|
||||
}
|
||||
|
||||
private function createFocus(string $name): Focus
|
||||
{
|
||||
$focus = new Focus();
|
||||
$focus->setName($name);
|
||||
$focus->setType('link');
|
||||
$focus->setStyle('modal');
|
||||
$focus->setProperties([
|
||||
'bar' => [
|
||||
'allow_hide' => 1,
|
||||
'push_page' => 1,
|
||||
'sticky' => 1,
|
||||
'size' => 'large',
|
||||
'placement' => 'top',
|
||||
],
|
||||
'modal' => [
|
||||
'placement' => 'top',
|
||||
],
|
||||
'notification' => [
|
||||
'placement' => 'top_left',
|
||||
],
|
||||
'page' => [],
|
||||
'animate' => 0,
|
||||
'link_activation' => 1,
|
||||
'colors' => [
|
||||
'primary' => '4e5d9d',
|
||||
'text' => '000000',
|
||||
'button' => 'fdb933',
|
||||
'button_text' => 'ffffff',
|
||||
],
|
||||
'content' => [
|
||||
'headline' => null,
|
||||
'tagline' => null,
|
||||
'link_text' => null,
|
||||
'link_url' => null,
|
||||
'link_new_window' => 1,
|
||||
'font' => 'Arial, Helvetica, sans-serif',
|
||||
'css' => null,
|
||||
],
|
||||
'when' => 'immediately',
|
||||
'timeout' => null,
|
||||
'frequency' => 'everypage',
|
||||
'stop_after_conversion' => 1,
|
||||
]);
|
||||
|
||||
return $focus;
|
||||
}
|
||||
|
||||
private function createLead(): Lead
|
||||
{
|
||||
$lead = new Lead();
|
||||
$lead->setFirstname('Contact');
|
||||
$lead->setEmail('test@test.com');
|
||||
$this->em->persist($lead);
|
||||
$this->em->flush();
|
||||
|
||||
return $lead;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticFocusBundle\Tests\Controller;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\Focus;
|
||||
use MauticPlugin\MauticFocusBundle\Model\FocusModel;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
final class FocusControllerTest extends MauticMysqlTestCase
|
||||
{
|
||||
public function testIndexActionIsSuccessful(): void
|
||||
{
|
||||
$this->client->request(Request::METHOD_GET, '/s/focus');
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertEquals(Response::HTTP_OK, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testNewActionIsSuccessful(): void
|
||||
{
|
||||
$this->client->request(Request::METHOD_GET, '/s/focus/new');
|
||||
$response = $this->client->getResponse();
|
||||
|
||||
$this->assertEquals(Response::HTTP_OK, $response->getStatusCode());
|
||||
}
|
||||
|
||||
public function testRecentActivityFeedOnFocusDetailsPage(): void
|
||||
{
|
||||
$focus = new Focus();
|
||||
$focus->setName('Test Focus');
|
||||
$focus->setType('link');
|
||||
$focus->setStyle('modal');
|
||||
$focus->setProperties([
|
||||
'bar' => [
|
||||
'allow_hide' => 1,
|
||||
'push_page' => 1,
|
||||
'sticky' => 1,
|
||||
'size' => 'large',
|
||||
'placement' => 'top',
|
||||
],
|
||||
'modal' => [
|
||||
'placement' => 'top',
|
||||
],
|
||||
'notification' => [
|
||||
'placement' => 'top_left',
|
||||
],
|
||||
'page' => [],
|
||||
'animate' => 0,
|
||||
'link_activation' => 1,
|
||||
'colors' => [
|
||||
'primary' => '4e5d9d',
|
||||
'text' => '000000',
|
||||
'button' => 'fdb933',
|
||||
'button_text' => 'ffffff',
|
||||
],
|
||||
'content' => [
|
||||
'headline' => null,
|
||||
'tagline' => null,
|
||||
'link_text' => null,
|
||||
'link_url' => null,
|
||||
'link_new_window' => 1,
|
||||
'font' => 'Arial, Helvetica, sans-serif',
|
||||
'css' => null,
|
||||
],
|
||||
'when' => 'immediately',
|
||||
'timeout' => null,
|
||||
'frequency' => 'everypage',
|
||||
'stop_after_conversion' => 1,
|
||||
]);
|
||||
|
||||
/** @var FocusModel $focusModel */
|
||||
$focusModel = static::getContainer()->get('mautic.focus.model.focus');
|
||||
$focusModel->saveEntity($focus);
|
||||
|
||||
$this->em->clear();
|
||||
|
||||
$crawler = $this->client->request(Request::METHOD_GET, '/s/focus/edit/'.$focus->getId());
|
||||
$this->assertResponseIsSuccessful();
|
||||
$form = $crawler->selectButton('focus_buttons_apply')->form();
|
||||
$form['focus[isPublished]']->setValue('0');
|
||||
$this->client->submit($form);
|
||||
|
||||
$crawler = $this->client->request(Request::METHOD_GET, '/s/focus/view/'.$focus->getId());
|
||||
$this->assertResponseIsSuccessful();
|
||||
|
||||
$translator = self::getContainer()->get('translator');
|
||||
|
||||
$this->assertStringContainsString($translator->trans('mautic.core.recent.activity'), $this->client->getResponse()->getContent());
|
||||
$this->assertCount(2, $crawler->filterXPath('//ul[contains(@class, "media-list-feed")]/li'));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticFocusBundle\Tests\Controller;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\Focus;
|
||||
use MauticPlugin\MauticFocusBundle\Model\FocusModel;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
class FocusPublicControllerFunctionalTest extends MauticMysqlTestCase
|
||||
{
|
||||
public function testGenerateFocusItemScript(): void
|
||||
{
|
||||
/** @var FocusModel $focusModel */
|
||||
$focusModel = static::getContainer()->get('mautic.focus.model.focus');
|
||||
$focus = $this->createFocus('popup');
|
||||
$focusModel->saveEntity($focus);
|
||||
|
||||
$this->client->request(Request::METHOD_GET, "/focus/{$focus->getId()}.js");
|
||||
$response = $this->client->getResponse();
|
||||
$this->assertTrue($response->isOk());
|
||||
$this->assertNotEmpty($response->getContent());
|
||||
}
|
||||
|
||||
public function testInactiveFocusItemScript(): void
|
||||
{
|
||||
/** @var FocusModel $focusModel */
|
||||
$focusModel = static::getContainer()->get('mautic.focus.model.focus');
|
||||
$focus = $this->createFocus('popup');
|
||||
$focus->setIsPublished(false);
|
||||
$focusModel->saveEntity($focus);
|
||||
|
||||
$this->client->request(Request::METHOD_GET, "/focus/{$focus->getId()}.js");
|
||||
$response = $this->client->getResponse();
|
||||
$this->assertTrue($response->isNotFound());
|
||||
$this->assertEmpty($response->getContent());
|
||||
}
|
||||
|
||||
private function createFocus(string $name): Focus
|
||||
{
|
||||
$focus = new Focus();
|
||||
$focus->setName($name);
|
||||
$focus->setType('link');
|
||||
$focus->setStyle('modal');
|
||||
$focus->setProperties([
|
||||
'bar' => [
|
||||
'allow_hide' => 1,
|
||||
'push_page' => 1,
|
||||
'sticky' => 1,
|
||||
'size' => 'large',
|
||||
'placement' => 'top',
|
||||
],
|
||||
'modal' => [
|
||||
'placement' => 'top',
|
||||
],
|
||||
'notification' => [
|
||||
'placement' => 'top_left',
|
||||
],
|
||||
'page' => [],
|
||||
'animate' => 0,
|
||||
'link_activation' => 1,
|
||||
'colors' => [
|
||||
'primary' => '4e5d9d',
|
||||
'text' => '000000',
|
||||
'button' => 'fdb933',
|
||||
'button_text' => 'ffffff',
|
||||
],
|
||||
'content' => [
|
||||
'headline' => null,
|
||||
'tagline' => null,
|
||||
'link_text' => null,
|
||||
'link_url' => null,
|
||||
'link_new_window' => 1,
|
||||
'font' => 'Arial, Helvetica, sans-serif',
|
||||
'css' => null,
|
||||
],
|
||||
'when' => 'immediately',
|
||||
'timeout' => null,
|
||||
'frequency' => 'everypage',
|
||||
'stop_after_conversion' => 1,
|
||||
]);
|
||||
|
||||
return $focus;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticFocusBundle\Tests\Entity;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Mautic\PageBundle\Entity\Hit;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\Focus;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\Stat;
|
||||
use MauticPlugin\MauticFocusBundle\Model\FocusModel;
|
||||
|
||||
class StatRepositoryFunctionalTest extends MauticMysqlTestCase
|
||||
{
|
||||
private FocusModel $focusModel;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->focusModel = static::$kernel->getContainer()->get('mautic.focus.model.focus');
|
||||
$this->setTestsData($this->createLead(), $this->focusModel);
|
||||
}
|
||||
|
||||
public function testGetStatsViewByLead(): void
|
||||
{
|
||||
$this->assertCount(5, $this->focusModel->getStatRepository()->getStatsViewByLead());
|
||||
}
|
||||
|
||||
public function testGetStatsClickByLead(): void
|
||||
{
|
||||
$this->assertCount(2, $this->focusModel->getStatRepository()->getStatsClickByLead());
|
||||
}
|
||||
|
||||
private function createLead(): Lead
|
||||
{
|
||||
$lead = new Lead();
|
||||
$lead->setFirstname('Contact');
|
||||
$lead->setEmail('test@test.com');
|
||||
$this->em->persist($lead);
|
||||
$this->em->flush();
|
||||
|
||||
return $lead;
|
||||
}
|
||||
|
||||
private function setTestsData(Lead $lead, FocusModel $focusModel): void
|
||||
{
|
||||
$focusPopupA = $this->createFocus('popup focus A');
|
||||
$focusPopupB = $this->createFocus('popup focus B');
|
||||
$focusPopupC = $this->createFocus('popup focus C');
|
||||
|
||||
$focusBarA = $this->createFocus('bar focus A');
|
||||
$focusBarB = $this->createFocus('bar focus B');
|
||||
|
||||
$this->focusModel->saveEntity($focusPopupA);
|
||||
$this->focusModel->saveEntity($focusPopupB);
|
||||
$this->focusModel->saveEntity($focusPopupC);
|
||||
|
||||
$this->focusModel->saveEntity($focusBarA);
|
||||
$this->focusModel->saveEntity($focusBarB);
|
||||
|
||||
$hitPopupA = new Hit();
|
||||
$hitPopupA->setLead($lead);
|
||||
|
||||
$hitBarB = new Hit();
|
||||
$hitBarB->setLead($lead);
|
||||
|
||||
$this->focusModel->addStat($focusPopupA, Stat::TYPE_NOTIFICATION, null, $lead);
|
||||
$this->focusModel->addStat($focusPopupB, Stat::TYPE_NOTIFICATION, null, $lead);
|
||||
$this->focusModel->addStat($focusPopupB, Stat::TYPE_CLICK, $hitPopupA, $lead);
|
||||
$this->focusModel->addStat($focusPopupC, Stat::TYPE_NOTIFICATION, null, $lead);
|
||||
|
||||
$this->focusModel->addStat($focusBarA, Stat::TYPE_NOTIFICATION, null, $lead);
|
||||
$this->focusModel->addStat($focusBarA, Stat::TYPE_CLICK, $hitBarB, $lead);
|
||||
$this->focusModel->addStat($focusBarB, Stat::TYPE_NOTIFICATION, null, $lead);
|
||||
}
|
||||
|
||||
private function createFocus(string $name): Focus
|
||||
{
|
||||
$focus = new Focus();
|
||||
$focus->setName($name);
|
||||
$focus->setType('link');
|
||||
$focus->setStyle('modal');
|
||||
$focus->setProperties([
|
||||
'bar' => [
|
||||
'allow_hide' => 1,
|
||||
'push_page' => 1,
|
||||
'sticky' => 1,
|
||||
'size' => 'large',
|
||||
'placement' => 'top',
|
||||
],
|
||||
'modal' => [
|
||||
'placement' => 'top',
|
||||
],
|
||||
'notification' => [
|
||||
'placement' => 'top_left',
|
||||
],
|
||||
'page' => [],
|
||||
'animate' => 0,
|
||||
'link_activation' => 1,
|
||||
'colors' => [
|
||||
'primary' => '4e5d9d',
|
||||
'text' => '000000',
|
||||
'button' => 'fdb933',
|
||||
'button_text' => 'ffffff',
|
||||
],
|
||||
'content' => [
|
||||
'headline' => null,
|
||||
'tagline' => null,
|
||||
'link_text' => null,
|
||||
'link_url' => null,
|
||||
'link_new_window' => 1,
|
||||
'font' => 'Arial, Helvetica, sans-serif',
|
||||
'css' => null,
|
||||
],
|
||||
'when' => 'immediately',
|
||||
'timeout' => null,
|
||||
'frequency' => 'everypage',
|
||||
'stop_after_conversion' => 1,
|
||||
]);
|
||||
|
||||
return $focus;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticFocusBundle\Tests\EventListener;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Mautic\PageBundle\Entity\Hit;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\Focus;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\Stat;
|
||||
use MauticPlugin\MauticFocusBundle\Model\FocusModel;
|
||||
|
||||
class LeadSubscriberFunctionalTest extends MauticMysqlTestCase
|
||||
{
|
||||
private Lead $lead;
|
||||
|
||||
private FocusModel $focusModel;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->focusModel = static::getContainer()->get('mautic.focus.model.focus');
|
||||
$this->lead = $this->createLead();
|
||||
|
||||
$this->setTestsData($this->lead, $this->focusModel);
|
||||
}
|
||||
|
||||
public function testSearchPhraseInNameFocusStat(): void
|
||||
{
|
||||
$this->assertCount(3, $this->searchPhrase('bar', $this->lead, $this->focusModel));
|
||||
$this->assertCount(4, $this->searchPhrase('popup', $this->lead, $this->focusModel));
|
||||
$this->assertCount(2, $this->searchPhrase('popup focus B', $this->lead, $this->focusModel));
|
||||
}
|
||||
|
||||
public function testSearchPhraseInTypeFocusStat(): void
|
||||
{
|
||||
$this->assertCount(2, $this->searchPhrase('click', $this->lead, $this->focusModel));
|
||||
$this->assertCount(5, $this->searchPhrase('view', $this->lead, $this->focusModel));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function searchPhrase(string $phrase, Lead $lead, FocusModel $focusModel): array
|
||||
{
|
||||
$searchViewStats = $focusModel->getStatRepository()->getStatsViewByLead((int) $lead->getId(), ['search'=>$phrase]);
|
||||
$searchClickStats = $focusModel->getStatRepository()->getStatsClickByLead((int) $lead->getId(), ['search'=>$phrase]);
|
||||
|
||||
return array_merge($searchViewStats, $searchClickStats);
|
||||
}
|
||||
|
||||
private function setTestsData(Lead $lead, FocusModel $focusModel): void
|
||||
{
|
||||
$focusPopupA = $this->createFocus('popup focus A');
|
||||
$focusPopupB = $this->createFocus('popup focus B');
|
||||
$focusPopupC = $this->createFocus('popup focus C');
|
||||
|
||||
$focusBarA = $this->createFocus('bar focus A');
|
||||
$focusBarB = $this->createFocus('bar focus B');
|
||||
|
||||
$this->focusModel->saveEntity($focusPopupA);
|
||||
$this->focusModel->saveEntity($focusPopupB);
|
||||
$this->focusModel->saveEntity($focusPopupC);
|
||||
|
||||
$this->focusModel->saveEntity($focusBarA);
|
||||
$this->focusModel->saveEntity($focusBarB);
|
||||
|
||||
$hitPopupA = new Hit();
|
||||
$hitPopupA->setLead($lead);
|
||||
|
||||
$hitBarB = new Hit();
|
||||
$hitBarB->setLead($lead);
|
||||
|
||||
$this->focusModel->addStat($focusPopupA, Stat::TYPE_NOTIFICATION, null, $lead);
|
||||
$this->focusModel->addStat($focusPopupB, Stat::TYPE_NOTIFICATION, null, $lead);
|
||||
$this->focusModel->addStat($focusPopupB, Stat::TYPE_CLICK, $hitPopupA, $lead);
|
||||
$this->focusModel->addStat($focusPopupC, Stat::TYPE_NOTIFICATION, null, $lead);
|
||||
|
||||
$this->focusModel->addStat($focusBarA, Stat::TYPE_NOTIFICATION, null, $lead);
|
||||
$this->focusModel->addStat($focusBarA, Stat::TYPE_CLICK, $hitBarB, $lead);
|
||||
$this->focusModel->addStat($focusBarB, Stat::TYPE_NOTIFICATION, null, $lead);
|
||||
}
|
||||
|
||||
private function createFocus(string $name): Focus
|
||||
{
|
||||
$focus = new Focus();
|
||||
$focus->setName($name);
|
||||
$focus->setType('link');
|
||||
$focus->setStyle('modal');
|
||||
$focus->setProperties([
|
||||
'bar' => [
|
||||
'allow_hide' => 1,
|
||||
'push_page' => 1,
|
||||
'sticky' => 1,
|
||||
'size' => 'large',
|
||||
'placement' => 'top',
|
||||
],
|
||||
'modal' => [
|
||||
'placement' => 'top',
|
||||
],
|
||||
'notification' => [
|
||||
'placement' => 'top_left',
|
||||
],
|
||||
'page' => [],
|
||||
'animate' => 0,
|
||||
'link_activation' => 1,
|
||||
'colors' => [
|
||||
'primary' => '4e5d9d',
|
||||
'text' => '000000',
|
||||
'button' => 'fdb933',
|
||||
'button_text' => 'ffffff',
|
||||
],
|
||||
'content' => [
|
||||
'headline' => null,
|
||||
'tagline' => null,
|
||||
'link_text' => null,
|
||||
'link_url' => null,
|
||||
'link_new_window' => 1,
|
||||
'font' => 'Arial, Helvetica, sans-serif',
|
||||
'css' => null,
|
||||
],
|
||||
'when' => 'immediately',
|
||||
'timeout' => null,
|
||||
'frequency' => 'everypage',
|
||||
'stop_after_conversion' => 1,
|
||||
]);
|
||||
|
||||
return $focus;
|
||||
}
|
||||
|
||||
private function createLead(): Lead
|
||||
{
|
||||
$lead = new Lead();
|
||||
$lead->setFirstname('Contact');
|
||||
$lead->setEmail('test@test.com');
|
||||
$this->em->persist($lead);
|
||||
$this->em->flush();
|
||||
|
||||
return $lead;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticFocusBundle\Tests\EventListener;
|
||||
|
||||
use Mautic\CoreBundle\Tests\CommonMocks;
|
||||
use Mautic\CoreBundle\Translation\Translator;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Mautic\LeadBundle\Event\LeadTimelineEvent;
|
||||
use Mautic\LeadBundle\LeadEvents;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\Stat;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\StatRepository;
|
||||
use MauticPlugin\MauticFocusBundle\EventListener\LeadSubscriber;
|
||||
use MauticPlugin\MauticFocusBundle\FocusEventTypes;
|
||||
use MauticPlugin\MauticFocusBundle\Model\FocusModel;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcher;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
|
||||
class LeadSubscriberTest extends CommonMocks
|
||||
{
|
||||
/**
|
||||
* @var Translator|MockObject
|
||||
*/
|
||||
private MockObject $translator;
|
||||
|
||||
/**
|
||||
* @var RouterInterface|MockObject
|
||||
*/
|
||||
private MockObject $router;
|
||||
|
||||
/**
|
||||
* @var FocusModel|(FocusModel&MockObject)|MockObject
|
||||
*/
|
||||
private MockObject $focusModel;
|
||||
|
||||
/**
|
||||
* @var StatRepository|(StatRepository&MockObject)|MockObject
|
||||
*/
|
||||
private MockObject $statRepository;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const EVENT_TYPE_VIEW_NAME = 'Focus view';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const EVENT_TYPE_CLICK_NAME = 'Focus click';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private const FOCUS_NAME = 'test Focus Item';
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->translator = $this->createMock(Translator::class);
|
||||
$this->router = $this->createMock(RouterInterface::class);
|
||||
$this->focusModel = $this->createMock(FocusModel::class);
|
||||
$this->statRepository = $this->createMock(StatRepository::class);
|
||||
$matcher = $this->any();
|
||||
|
||||
$this->translator->expects($matcher)
|
||||
->method('trans')->willReturnCallback(function (...$parameters) use ($matcher) {
|
||||
if (1 === $matcher->numberOfInvocations()) {
|
||||
$this->assertSame('mautic.focus.event.view', $parameters[0]);
|
||||
|
||||
return self::EVENT_TYPE_VIEW_NAME;
|
||||
}
|
||||
if (2 === $matcher->numberOfInvocations()) {
|
||||
$this->assertSame('mautic.focus.event.click', $parameters[0]);
|
||||
|
||||
return self::EVENT_TYPE_CLICK_NAME;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that on timeline entry is created for a lead
|
||||
* that was displayed Focus Item.
|
||||
*/
|
||||
public function testShowFocusItem(): void
|
||||
{
|
||||
$lead = $this->getLead();
|
||||
$date = new \DateTime();
|
||||
|
||||
$this->mockFocusModelGetStatsByLead(Stat::TYPE_NOTIFICATION, self::FOCUS_NAME, 'getStatsViewByLead', $date);
|
||||
|
||||
$timelineEvent = $this->getTimelineEvent(
|
||||
FocusEventTypes::FOCUS_ON_VIEW, self::EVENT_TYPE_VIEW_NAME, self::FOCUS_NAME, $date, $lead
|
||||
);
|
||||
|
||||
$leadEvent = new LeadTimelineEvent($lead);
|
||||
$subscriber = new LeadSubscriber(
|
||||
$this->translator,
|
||||
$this->router,
|
||||
$this->focusModel
|
||||
);
|
||||
|
||||
$dispatcher = new EventDispatcher();
|
||||
$dispatcher->addSubscriber($subscriber);
|
||||
$dispatcher->dispatch($leadEvent, LeadEvents::TIMELINE_ON_GENERATE);
|
||||
|
||||
$this->assertSame([$timelineEvent], $leadEvent->getEvents());
|
||||
}
|
||||
|
||||
public function testShowFocusItemWhenNoLead(): void
|
||||
{
|
||||
$date = new \DateTime();
|
||||
|
||||
$this->mockFocusModelGetStatsByLead(Stat::TYPE_NOTIFICATION, self::FOCUS_NAME, 'getStatsViewByLead', $date);
|
||||
|
||||
$timelineEvent = $this->getTimelineEvent(
|
||||
FocusEventTypes::FOCUS_ON_VIEW, self::EVENT_TYPE_VIEW_NAME, self::FOCUS_NAME, $date
|
||||
);
|
||||
|
||||
$leadEvent = new LeadTimelineEvent();
|
||||
$subscriber = new LeadSubscriber(
|
||||
$this->translator,
|
||||
$this->router,
|
||||
$this->focusModel
|
||||
);
|
||||
|
||||
$dispatcher = new EventDispatcher();
|
||||
$dispatcher->addSubscriber($subscriber);
|
||||
$dispatcher->dispatch($leadEvent, LeadEvents::TIMELINE_ON_GENERATE);
|
||||
|
||||
$this->assertSame([$timelineEvent], $leadEvent->getEvents());
|
||||
}
|
||||
|
||||
/**
|
||||
* Make sure that on timeline entry is created for a lead
|
||||
* that was clicked Focus Item.
|
||||
*/
|
||||
public function testClickFocusItem(): void
|
||||
{
|
||||
$lead = $this->getLead();
|
||||
$date = new \DateTime();
|
||||
|
||||
$this->mockFocusModelGetStatsByLead(Stat::TYPE_CLICK, self::FOCUS_NAME, 'getStatsClickByLead', $date);
|
||||
|
||||
$timelineEvent = $this->getTimelineEvent(
|
||||
FocusEventTypes::FOCUS_ON_CLICK, self::EVENT_TYPE_CLICK_NAME, self::FOCUS_NAME, $date, $lead
|
||||
);
|
||||
|
||||
$leadEvent = new LeadTimelineEvent($lead);
|
||||
$subscriber = new LeadSubscriber(
|
||||
$this->translator,
|
||||
$this->router,
|
||||
$this->focusModel
|
||||
);
|
||||
|
||||
$dispatcher = new EventDispatcher();
|
||||
$dispatcher->addSubscriber($subscriber);
|
||||
$dispatcher->dispatch($leadEvent, LeadEvents::TIMELINE_ON_GENERATE);
|
||||
|
||||
$this->assertSame([$timelineEvent], $leadEvent->getEvents());
|
||||
}
|
||||
|
||||
public function testClickFocusItemWhenNoLead(): void
|
||||
{
|
||||
$date = new \DateTime();
|
||||
|
||||
$this->mockFocusModelGetStatsByLead(Stat::TYPE_CLICK, self::FOCUS_NAME, 'getStatsClickByLead', $date);
|
||||
|
||||
$timelineEvent = $this->getTimelineEvent(
|
||||
FocusEventTypes::FOCUS_ON_CLICK, self::EVENT_TYPE_CLICK_NAME, self::FOCUS_NAME, $date
|
||||
);
|
||||
|
||||
$leadEvent = new LeadTimelineEvent();
|
||||
$subscriber = new LeadSubscriber(
|
||||
$this->translator,
|
||||
$this->router,
|
||||
$this->focusModel
|
||||
);
|
||||
|
||||
$dispatcher = new EventDispatcher();
|
||||
$dispatcher->addSubscriber($subscriber);
|
||||
$dispatcher->dispatch($leadEvent, LeadEvents::TIMELINE_ON_GENERATE);
|
||||
|
||||
$this->assertSame([$timelineEvent], $leadEvent->getEvents());
|
||||
}
|
||||
|
||||
private function mockFocusModelGetStatsByLead(string $statType, string $focusName, string $method, \DateTime $date): void
|
||||
{
|
||||
$stats = [
|
||||
'results'=> [
|
||||
[
|
||||
'id' => 1,
|
||||
'type' => $statType,
|
||||
'date_added' => $date,
|
||||
'focus_id' => 1,
|
||||
'focus_name' => $focusName,
|
||||
],
|
||||
],
|
||||
'total'=> 1,
|
||||
];
|
||||
|
||||
$this->statRepository->method($method)->willReturn($stats);
|
||||
$this->focusModel->method('getStatRepository')->willReturn($this->statRepository);
|
||||
}
|
||||
|
||||
private function getLead(): Lead
|
||||
{
|
||||
$lead = new Lead();
|
||||
$lead->setId(1);
|
||||
|
||||
return $lead;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
private function getTimelineEvent(string $eventType, string $eventTypeName, string $focusName, \DateTime $date, ?Lead $lead=null): array
|
||||
{
|
||||
$leadEventLogId = 1;
|
||||
|
||||
return [
|
||||
'event' => $eventType,
|
||||
'eventId' => $eventType.'.'.$leadEventLogId,
|
||||
'eventLabel' => [
|
||||
'label' => $focusName,
|
||||
'href' => '',
|
||||
],
|
||||
'eventType' => $eventTypeName,
|
||||
'timestamp' => $date,
|
||||
'icon' => 'ri-search-line',
|
||||
'contactId' => $lead?->getId(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticFocusBundle\Tests\EventListener;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Mautic\PageBundle\Entity\Redirect;
|
||||
use Mautic\PageBundle\Entity\Trackable;
|
||||
use Mautic\ReportBundle\Entity\Report;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\Focus;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\Stat;
|
||||
use MauticPlugin\MauticFocusBundle\EventListener\ReportSubscriber;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
|
||||
final class ReportSubscriberFunctionalTest extends MauticMysqlTestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
public function testGenerateFocusItemReportWithAllAvailableColumns(): void
|
||||
{
|
||||
$this->fillDatabase();
|
||||
|
||||
$report = new Report();
|
||||
$report->setName('Focus Stats Report');
|
||||
$report->setSource(ReportSubscriber::CONTEXT_FOCUS_STATS);
|
||||
$report->setColumns([ReportSubscriber::PREFIX_FOCUS.'.name', ReportSubscriber::PREFIX_FOCUS.'.description', ReportSubscriber::PREFIX_FOCUS.'.focus_type', ReportSubscriber::PREFIX_FOCUS.'.style', ReportSubscriber::PREFIX_STATS.'.type', ReportSubscriber::PREFIX_TRACKABLES.'.hits', ReportSubscriber::PREFIX_TRACKABLES.'.unique_hits', ReportSubscriber::PREFIX_REDIRECTS.'.url',
|
||||
]);
|
||||
$this->em->persist($report);
|
||||
$this->em->flush();
|
||||
|
||||
$crawler = $this->client->request(Request::METHOD_GET, "/s/reports/view/{$report->getId()}");
|
||||
$this->assertTrue($this->client->getResponse()->isOk());
|
||||
// get table with id=reportTable
|
||||
$crawlerTable = $crawler->filter('#reportTable');
|
||||
// remove first line of table (column names)
|
||||
$table = array_slice($this->domTableToArray($crawlerTable), 1);
|
||||
// remove last line of table (unnecessary part generated by js)
|
||||
array_pop($table);
|
||||
|
||||
$this->assertSame([
|
||||
['1', 'FocusItem1', 'doesAbc', 'link', 'modal', 'click', '1', '1', 'http://example1.com'],
|
||||
['2', 'FocusItem1', 'doesAbc', 'link', 'modal', 'view', '3', '2', 'http://example1.com'],
|
||||
['3', 'FocusItem2', 'doesAbcd', 'link', 'modal', 'click', '1', '1', 'http://example2.com'],
|
||||
['4', 'FocusItem2', 'doesAbcd', 'link', 'modal', 'view', '1', '1', 'http://example2.com'],
|
||||
], $table);
|
||||
}
|
||||
|
||||
public function testGenerateFocusItemReportFocusLeadsColumns(): void
|
||||
{
|
||||
$this->fillDatabase();
|
||||
|
||||
$report = new Report();
|
||||
$report->setName('Focus Leads Report');
|
||||
$report->setSource(ReportSubscriber::CONTEXT_FOCUS_LEADS);
|
||||
$report->setColumns(
|
||||
[
|
||||
ReportSubscriber::PREFIX_LEADS.'.email',
|
||||
ReportSubscriber::PREFIX_FOCUS.'.name',
|
||||
ReportSubscriber::PREFIX_FOCUS.'.description',
|
||||
ReportSubscriber::PREFIX_FOCUS.'.focus_type',
|
||||
ReportSubscriber::PREFIX_FOCUS.'.style',
|
||||
ReportSubscriber::PREFIX_STATS.'.type',
|
||||
ReportSubscriber::PREFIX_TRACKABLES.'.hits',
|
||||
ReportSubscriber::PREFIX_REDIRECTS.'.url',
|
||||
]
|
||||
);
|
||||
$this->em->persist($report);
|
||||
$this->em->flush();
|
||||
|
||||
$crawler = $this->client->request(Request::METHOD_GET, "/s/reports/view/{$report->getId()}");
|
||||
$this->assertTrue($this->client->getResponse()->isOk());
|
||||
|
||||
// get table with id=reportTable
|
||||
$crawlerTable = $crawler->filter('#reportTable');
|
||||
// remove first line of table (column names)
|
||||
$table = array_slice($this->domTableToArray($crawlerTable), 1);
|
||||
// remove last line of table (unnecessary part generated by js)
|
||||
array_pop($table);
|
||||
|
||||
$this->assertSame([
|
||||
['1', 'lead.1@example.com', 'FocusItem1', 'doesAbc', 'link', 'modal', 'click', '1', 'http://example1.com'],
|
||||
['2', 'lead.1@example.com', 'FocusItem1', 'doesAbc', 'link', 'modal', 'view', '2', 'http://example1.com'],
|
||||
['3', 'lead.2@example.com', 'FocusItem1', 'doesAbc', 'link', 'modal', 'view', '1', 'http://example1.com'],
|
||||
['4', 'lead.2@example.com', 'FocusItem2', 'doesAbcd', 'link', 'modal', 'click', '1', 'http://example2.com'],
|
||||
['5', 'lead.2@example.com', 'FocusItem2', 'doesAbcd', 'link', 'modal', 'view', '1', 'http://example2.com'],
|
||||
], $table);
|
||||
}
|
||||
|
||||
private function fillDatabase(): void
|
||||
{
|
||||
$lead1= $this->createContact('lead.1@example.com');
|
||||
$lead2= $this->createContact('lead.2@example.com');
|
||||
|
||||
$focus1 = $this->createFocusItem('FocusItem1', 'doesAbc', 'link', 'modal');
|
||||
$focus2 = $this->createFocusItem('FocusItem2', 'doesAbcd', 'link', 'modal');
|
||||
$focus3 = $this->createFocusItem('FocusItem3', 'doesAbcde', 'link', 'modal');
|
||||
$this->em->flush();
|
||||
|
||||
$date = new \DateTime();
|
||||
$this->createFocusStats('click', $focus1, $lead1, $date);
|
||||
$this->createFocusStats('click', $focus2, $lead2, $date);
|
||||
$this->createFocusStats('view', $focus1, $lead1, $date);
|
||||
$this->createFocusStats('view', $focus1, $lead1, $date);
|
||||
$this->createFocusStats('view', $focus1, $lead2, $date);
|
||||
$this->createFocusStats('view', $focus2, $lead2, $date);
|
||||
|
||||
/** @var int $focusId1 */
|
||||
$focusId1 = $focus1->getId();
|
||||
/** @var int $focusId2 */
|
||||
$focusId2 = $focus2->getId();
|
||||
$this->createTrackableAndRedirects('http://example1.com', $focusId1, 1, 1);
|
||||
$this->createTrackableAndRedirects('http://example2.com', $focusId2, 1, 1);
|
||||
$this->createTrackableAndRedirects('http://example2.com', $focusId2);
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
}
|
||||
|
||||
private function createContact(string $email): Lead
|
||||
{
|
||||
$contact = new Lead();
|
||||
$contact->setEmail($email);
|
||||
$this->em->persist($contact);
|
||||
|
||||
return $contact;
|
||||
}
|
||||
|
||||
private function createFocusItem(string $name, string $description, string $focusType, string $style): Focus
|
||||
{
|
||||
$focus = new Focus();
|
||||
$focus->setName($name);
|
||||
$focus->setDescription($description);
|
||||
$focus->setType($focusType);
|
||||
$focus->setStyle($style);
|
||||
$this->em->persist($focus);
|
||||
|
||||
return $focus;
|
||||
}
|
||||
|
||||
private function createFocusStats(string $type, Focus $focus, Lead $lead, \DateTime $dateAdded): void
|
||||
{
|
||||
$focusStats = new Stat();
|
||||
$focusStats->setType($type);
|
||||
$focusStats->setFocus($focus);
|
||||
$focusStats->setLead($lead);
|
||||
$focusStats->setDateAdded($dateAdded);
|
||||
$this->em->persist($focusStats);
|
||||
}
|
||||
|
||||
private function createTrackableAndRedirects(string $url, int $channelId, int $hits = 0, int $uniqueHits = 0): void
|
||||
{
|
||||
$redirect = new Redirect();
|
||||
$redirect->setRedirectId(uniqid());
|
||||
$redirect->setUrl($url);
|
||||
$redirect->setHits($hits);
|
||||
$redirect->setUniqueHits($uniqueHits);
|
||||
$this->em->persist($redirect);
|
||||
|
||||
$trackable = new Trackable();
|
||||
$trackable->setChannelId($channelId);
|
||||
$trackable->setChannel('focus');
|
||||
$trackable->setHits($hits);
|
||||
$trackable->setUniqueHits($uniqueHits);
|
||||
$trackable->setRedirect($redirect);
|
||||
$this->em->persist($trackable);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int,array<int,mixed>>
|
||||
*/
|
||||
private function domTableToArray(Crawler $crawler): array
|
||||
{
|
||||
return $crawler->filter('tr')->each(fn ($tr) => $tr->filter('td')->each(fn ($td) => trim($td->text())));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticFocusBundle\Tests\Form\Type;
|
||||
|
||||
use MauticPlugin\MauticFocusBundle\Form\Type\ContentType;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Form\FormBuilderInterface;
|
||||
|
||||
class ContentTypeTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var mixed|\PHPUnit\Framework\MockObject\MockObject|FormBuilderInterface
|
||||
*/
|
||||
private \PHPUnit\Framework\MockObject\MockObject $formBuilder;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->formBuilder = $this->createMock(FormBuilderInterface::class);
|
||||
}
|
||||
|
||||
public function testBuilderForm(): void
|
||||
{
|
||||
$this->formBuilder->expects(self::exactly(7))->method('add')->willReturnSelf();
|
||||
$options = [];
|
||||
$contentType = new ContentType();
|
||||
$contentType->buildForm($this->formBuilder, $options);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticFocusBundle\Tests\Functional\Controller;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\ProjectBundle\Entity\Project;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\Focus;
|
||||
use PHPUnit\Framework\Assert;
|
||||
|
||||
class FocusControllerTest extends MauticMysqlTestCase
|
||||
{
|
||||
public function testFocusWithProject(): void
|
||||
{
|
||||
$focus = new Focus();
|
||||
$focus->setName('Test Focus');
|
||||
$focus->setType('notice');
|
||||
$focus->setStyle('bar');
|
||||
$this->em->persist($focus);
|
||||
|
||||
$project = new Project();
|
||||
$project->setName('Test Project');
|
||||
$this->em->persist($project);
|
||||
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$crawler = $this->client->request('GET', '/s/focus/edit/'.$focus->getId());
|
||||
$form = $crawler->selectButton('Save')->form();
|
||||
$form['focus[projects]']->setValue((string) $project->getId());
|
||||
|
||||
$this->client->submit($form);
|
||||
|
||||
$this->assertResponseIsSuccessful();
|
||||
|
||||
$savedFocus = $this->em->find(Focus::class, $focus->getId());
|
||||
Assert::assertSame($project->getId(), $savedFocus->getProjects()->first()->getId());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticFocusBundle\Tests\Functional\Controller;
|
||||
|
||||
use Mautic\ProjectBundle\Tests\Functional\AbstractProjectSearchTestCase;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\Focus;
|
||||
|
||||
final class FocusProjectSearchFunctionalTest extends AbstractProjectSearchTestCase
|
||||
{
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('searchDataProvider')]
|
||||
public function testProjectSearch(string $searchTerm, array $expectedEntities, array $unexpectedEntities): void
|
||||
{
|
||||
$projectOne = $this->createProject('Project One');
|
||||
$projectTwo = $this->createProject('Project Two');
|
||||
$projectThree = $this->createProject('Project Three');
|
||||
|
||||
$focusAlpha = $this->createFocus('Focus Alpha');
|
||||
$focusBeta = $this->createFocus('Focus Beta');
|
||||
$this->createFocus('Focus Gamma');
|
||||
$this->createFocus('Focus Delta');
|
||||
|
||||
$focusAlpha->addProject($projectOne);
|
||||
$focusAlpha->addProject($projectTwo);
|
||||
$focusBeta->addProject($projectTwo);
|
||||
$focusBeta->addProject($projectThree);
|
||||
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$this->searchAndAssert($searchTerm, $expectedEntities, $unexpectedEntities, ['/api/focus', '/s/focus']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Generator<string, array{searchTerm: string, expectedEntities: array<string>, unexpectedEntities: array<string>}>
|
||||
*/
|
||||
public static function searchDataProvider(): \Generator
|
||||
{
|
||||
yield 'search by one project' => [
|
||||
'searchTerm' => 'project:"Project Two"',
|
||||
'expectedEntities' => ['Focus Alpha', 'Focus Beta'],
|
||||
'unexpectedEntities' => ['Focus Gamma', 'Focus Delta'],
|
||||
];
|
||||
|
||||
yield 'search by one project AND focus name' => [
|
||||
'searchTerm' => 'project:"Project Two" AND Beta',
|
||||
'expectedEntities' => ['Focus Beta'],
|
||||
'unexpectedEntities' => ['Focus Alpha', 'Focus Gamma', 'Focus Delta'],
|
||||
];
|
||||
|
||||
yield 'search by one project OR focus name' => [
|
||||
'searchTerm' => 'project:"Project Two" OR Gamma',
|
||||
'expectedEntities' => ['Focus Alpha', 'Focus Beta', 'Focus Gamma'],
|
||||
'unexpectedEntities' => ['Focus Delta'],
|
||||
];
|
||||
|
||||
yield 'search by NOT one project' => [
|
||||
'searchTerm' => '!project:"Project Two"',
|
||||
'expectedEntities' => ['Focus Gamma', 'Focus Delta'],
|
||||
'unexpectedEntities' => ['Focus Alpha', 'Focus Beta'],
|
||||
];
|
||||
|
||||
yield 'search by two projects with AND' => [
|
||||
'searchTerm' => 'project:"Project Two" AND project:"Project Three"',
|
||||
'expectedEntities' => ['Focus Beta'],
|
||||
'unexpectedEntities' => ['Focus Alpha', 'Focus Gamma', 'Focus Delta'],
|
||||
];
|
||||
|
||||
yield 'search by two projects with NOT AND' => [
|
||||
'searchTerm' => '!project:"Project Two" AND !project:"Project Three"',
|
||||
'expectedEntities' => ['Focus Gamma', 'Focus Delta'],
|
||||
'unexpectedEntities' => ['Focus Alpha', 'Focus Beta'],
|
||||
];
|
||||
|
||||
yield 'search by two projects with OR' => [
|
||||
'searchTerm' => 'project:"Project Two" OR project:"Project Three"',
|
||||
'expectedEntities' => ['Focus Alpha', 'Focus Beta'],
|
||||
'unexpectedEntities' => ['Focus Gamma', 'Focus Delta'],
|
||||
];
|
||||
|
||||
yield 'search by two projects with NOT OR' => [
|
||||
'searchTerm' => '!project:"Project Two" OR !project:"Project Three"',
|
||||
'expectedEntities' => ['Focus Alpha', 'Focus Gamma', 'Focus Delta'],
|
||||
'unexpectedEntities' => ['Focus Beta'],
|
||||
];
|
||||
}
|
||||
|
||||
private function createFocus(string $name): Focus
|
||||
{
|
||||
$focus = new Focus();
|
||||
$focus->setName($name);
|
||||
$focus->setType('notice');
|
||||
$focus->setStyle('bar');
|
||||
$this->em->persist($focus);
|
||||
|
||||
return $focus;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticFocusBundle\Tests\Functional\Controller;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\PageBundle\Entity\Redirect;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\Focus;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
|
||||
class PublicControllerTest extends MauticMysqlTestCase
|
||||
{
|
||||
#[\PHPUnit\Framework\Attributes\PreserveGlobalState(false)]
|
||||
#[\PHPUnit\Framework\Attributes\RunInSeparateProcess]
|
||||
public function testGenerateActionWithContactTokenInLinkUrl(): void
|
||||
{
|
||||
$linkUrl = 'https://{contactfield=site_url}/tour';
|
||||
$focus = new Focus();
|
||||
$focus->setName('Test');
|
||||
$focus->setType('link');
|
||||
$focus->setStyle('modal');
|
||||
$focus->setProperties([
|
||||
'content' => [
|
||||
'headline' => '',
|
||||
'link_text' => 'Link text',
|
||||
'link_url' => $linkUrl,
|
||||
'font' => 'Arial, Helvetica, sans-serif',
|
||||
'link_new_window' => 1,
|
||||
],
|
||||
'when' => 'immediately',
|
||||
'modal' => [
|
||||
'placement' => 'top',
|
||||
],
|
||||
'frequency' => 'everypage',
|
||||
'colors' => [
|
||||
'primary' => '#4e5d9d',
|
||||
'text' => '#000000',
|
||||
'button' => '#fdb933',
|
||||
'button_text' => '#ffffff',
|
||||
],
|
||||
]);
|
||||
$this->em->persist($focus);
|
||||
$this->em->flush();
|
||||
$this->em->clear();
|
||||
|
||||
$this->client->request(Request::METHOD_GET, sprintf('/focus/%s.js', $focus->getId()));
|
||||
$content = $this->client->getResponse()->getContent();
|
||||
|
||||
$redirects = $this->em->getRepository(Redirect::class)->findAll();
|
||||
Assert::assertCount(1, $redirects);
|
||||
|
||||
/** @var Redirect $redirect */
|
||||
$redirect = reset($redirects);
|
||||
Assert::assertSame($linkUrl, $redirect->getUrl());
|
||||
|
||||
$url = $this->router->generate('mautic_url_redirect', ['redirectId' => $redirect->getRedirectId()], UrlGeneratorInterface::ABSOLUTE_URL);
|
||||
$twig = $this->getContainer()->get('twig');
|
||||
if (!$twig->hasExtension(\Twig\Extension\EscaperExtension::class)) {
|
||||
$twig->addExtension(new \Twig\Extension\EscaperExtension());
|
||||
}
|
||||
$url = $twig->getRuntime(\Twig\Runtime\EscaperRuntime::class)->escape($url, 'js');
|
||||
Assert::assertStringContainsString($url, $content);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticFocusBundle\Tests\Model;
|
||||
|
||||
use Mautic\CoreBundle\Test\MauticMysqlTestCase;
|
||||
use Mautic\LeadBundle\Entity\Lead;
|
||||
use Mautic\PageBundle\Entity\Hit;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\Focus;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\Stat;
|
||||
use MauticPlugin\MauticFocusBundle\Model\FocusModel;
|
||||
|
||||
class FocusModelFunctionalTest extends MauticMysqlTestCase
|
||||
{
|
||||
private Lead $lead;
|
||||
|
||||
private FocusModel $focusModel;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->focusModel = static::getContainer()->get('mautic.focus.model.focus');
|
||||
$this->lead = $this->createLead();
|
||||
}
|
||||
|
||||
public function testGetStats(): void
|
||||
{
|
||||
$focusPopupA = $this->createFocus('popup focus A');
|
||||
$focusStatExpected = $this->setTestsData($this->lead, $focusPopupA);
|
||||
|
||||
$to = new \DateTime('+1 day');
|
||||
$from = new \DateTime('-1 month');
|
||||
|
||||
$focusStat = $this->focusModel->getStats($focusPopupA, null, $from, $to);
|
||||
|
||||
$focusViewsCount = array_sum($focusStat['datasets'][0]['data']);
|
||||
$focusClickCount = array_sum($focusStat['datasets'][1]['data']);
|
||||
|
||||
$this->assertEquals($focusStatExpected['view'], $focusViewsCount);
|
||||
$this->assertEquals($focusStatExpected['click'], $focusClickCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<string, int>
|
||||
*/
|
||||
private function setTestsData(Lead $lead, Focus $focus): array
|
||||
{
|
||||
$hitPopupA = new Hit();
|
||||
$hitPopupA->setLead($lead);
|
||||
|
||||
$this->focusModel->addStat($focus, Stat::TYPE_NOTIFICATION, null, $lead);
|
||||
$this->focusModel->addStat($focus, Stat::TYPE_CLICK, $hitPopupA, $lead);
|
||||
$this->focusModel->addStat($focus, Stat::TYPE_CLICK, $hitPopupA, $lead);
|
||||
$this->focusModel->addStat($focus, Stat::TYPE_CLICK, $hitPopupA, $lead);
|
||||
$this->focusModel->addStat($focus, Stat::TYPE_CLICK, $hitPopupA, $lead);
|
||||
|
||||
return ['view' => 1, 'click' => 4];
|
||||
}
|
||||
|
||||
private function createFocus(string $name): Focus
|
||||
{
|
||||
$focus = new Focus();
|
||||
$focus->setName($name);
|
||||
$focus->setType('link');
|
||||
$focus->setStyle('modal');
|
||||
$focus->setProperties([
|
||||
'bar' => [
|
||||
'allow_hide' => 1,
|
||||
'push_page' => 1,
|
||||
'sticky' => 1,
|
||||
'size' => 'large',
|
||||
'placement' => 'top',
|
||||
],
|
||||
'modal' => [
|
||||
'placement' => 'top',
|
||||
],
|
||||
'notification' => [
|
||||
'placement' => 'top_left',
|
||||
],
|
||||
'page' => [],
|
||||
'animate' => 0,
|
||||
'link_activation' => 1,
|
||||
'colors' => [
|
||||
'primary' => '4e5d9d',
|
||||
'text' => '000000',
|
||||
'button' => 'fdb933',
|
||||
'button_text' => 'ffffff',
|
||||
],
|
||||
'content' => [
|
||||
'headline' => null,
|
||||
'tagline' => null,
|
||||
'link_text' => null,
|
||||
'link_url' => null,
|
||||
'link_new_window' => 1,
|
||||
'font' => 'Arial, Helvetica, sans-serif',
|
||||
'css' => null,
|
||||
],
|
||||
'when' => 'immediately',
|
||||
'timeout' => null,
|
||||
'frequency' => 'everypage',
|
||||
'stop_after_conversion' => 1,
|
||||
]);
|
||||
|
||||
$this->focusModel->saveEntity($focus);
|
||||
|
||||
return $focus;
|
||||
}
|
||||
|
||||
private function createLead(): Lead
|
||||
{
|
||||
$lead = new Lead();
|
||||
$lead->setFirstname('Contact');
|
||||
$lead->setEmail('test@test.com');
|
||||
$this->em->persist($lead);
|
||||
$this->em->flush();
|
||||
|
||||
return $lead;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticFocusBundle\Tests\Model;
|
||||
|
||||
use Doctrine\ORM\EntityManagerInterface;
|
||||
use Mautic\CoreBundle\Helper\CoreParametersHelper;
|
||||
use Mautic\CoreBundle\Helper\UserHelper;
|
||||
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
|
||||
use Mautic\CoreBundle\Translation\Translator;
|
||||
use Mautic\FormBundle\Model\FormModel;
|
||||
use Mautic\LeadBundle\Model\FieldModel;
|
||||
use Mautic\LeadBundle\Tracker\ContactTracker;
|
||||
use Mautic\PageBundle\Model\TrackableModel;
|
||||
use MauticPlugin\MauticFocusBundle\Model\FocusModel;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\MockObject\Rule\InvokedCount;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Psr\Log\LoggerInterface;
|
||||
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Twig\Environment;
|
||||
|
||||
class FocusModelTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var ContactTracker|MockObject
|
||||
*/
|
||||
private MockObject $contactTracker;
|
||||
|
||||
/**
|
||||
* @var MockObject|EventDispatcherInterface
|
||||
*/
|
||||
private MockObject $dispatcher;
|
||||
|
||||
/**
|
||||
* @var FormModel|MockObject
|
||||
*/
|
||||
private MockObject $formModel;
|
||||
|
||||
/**
|
||||
* @var FieldModel|MockObject
|
||||
*/
|
||||
private MockObject $leadFieldModel;
|
||||
|
||||
/**
|
||||
* @var Environment|mixed|MockObject
|
||||
*/
|
||||
private MockObject $twig;
|
||||
|
||||
/**
|
||||
* @var TrackableModel|mixed|MockObject
|
||||
*/
|
||||
private MockObject $trackableModel;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$this->formModel = $this->createMock(FormModel::class);
|
||||
$this->trackableModel = $this->createMock(TrackableModel::class);
|
||||
$this->twig = $this->createMock(Environment::class);
|
||||
$this->dispatcher = $this->createMock(EventDispatcherInterface::class);
|
||||
$this->leadFieldModel = $this->createMock(FieldModel::class);
|
||||
$this->contactTracker = $this->createMock(ContactTracker::class);
|
||||
parent::setUp();
|
||||
}
|
||||
|
||||
#[\PHPUnit\Framework\Attributes\DataProvider('focusTypeProvider')]
|
||||
public function testGetContentWithForm(string $type, InvokedCount $count): void
|
||||
{
|
||||
$this->formModel->expects(self::once())->method('getPages')->willReturn(['', '']);
|
||||
|
||||
$this->formModel->expects($count)->method('getEntity');
|
||||
|
||||
$focusModel = new FocusModel(
|
||||
$this->formModel,
|
||||
$this->trackableModel,
|
||||
$this->twig,
|
||||
$this->leadFieldModel,
|
||||
$this->contactTracker,
|
||||
$this->createMock(EntityManagerInterface::class),
|
||||
$this->createMock(CorePermissions::class),
|
||||
$this->dispatcher,
|
||||
$this->createMock(UrlGeneratorInterface::class),
|
||||
$this->createMock(Translator::class),
|
||||
$this->createMock(UserHelper::class),
|
||||
$this->createMock(LoggerInterface::class),
|
||||
$this->createMock(CoreParametersHelper::class)
|
||||
);
|
||||
$focus = [
|
||||
'form' => 'xxx',
|
||||
'type' => $type,
|
||||
];
|
||||
|
||||
$focusModel->getContent($focus);
|
||||
}
|
||||
|
||||
public static function focusTypeProvider(): \Generator
|
||||
{
|
||||
yield ['form', self::once()];
|
||||
yield ['notice', self::never()];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
--TEST--
|
||||
compile LESS
|
||||
--TEMPLATE--
|
||||
{{ less|less_compile }}
|
||||
--DATA--
|
||||
return ['less' => "@primarycolor: #FF7F50;@color:#800080;h2{color: @primarycolor;}h3{color: @color;}"]
|
||||
--EXPECT--
|
||||
h2 {
|
||||
color: #FF7F50;
|
||||
}
|
||||
h3 {
|
||||
color: #800080;
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticFocusBundle\Tests\Twig;
|
||||
|
||||
use MauticPlugin\MauticFocusBundle\Twig\Extension\FocusBundleExtension;
|
||||
use Twig\Extension\ExtensionInterface;
|
||||
|
||||
/**
|
||||
* @see https://twig.symfony.com/doc/2.x/advanced.html#functional-tests
|
||||
*/
|
||||
class TwigIntegrationTest extends \Twig\Test\IntegrationTestCase
|
||||
{
|
||||
/**
|
||||
* @return ExtensionInterface[]
|
||||
*/
|
||||
public function getExtensions(): array
|
||||
{
|
||||
return [
|
||||
new FocusBundleExtension(),
|
||||
];
|
||||
}
|
||||
|
||||
public static function getFixturesDirectory(): string
|
||||
{
|
||||
return __DIR__.'/Fixtures/';
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
namespace MauticPlugin\MauticFocusBundle\Tests\Unit\Helper;
|
||||
|
||||
use MauticPlugin\MauticFocusBundle\Helper\IframeAvailabilityChecker;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Symfony\Contracts\Translation\TranslatorInterface;
|
||||
|
||||
class IframeAvailabilityCheckerTest extends \PHPUnit\Framework\TestCase
|
||||
{
|
||||
/**
|
||||
* @var MockObject&TranslatorInterface
|
||||
*/
|
||||
private MockObject $translator;
|
||||
|
||||
private IframeAvailabilityChecker $helper;
|
||||
|
||||
public function setUp(): void
|
||||
{
|
||||
$this->translator = $this->createMock(TranslatorInterface::class);
|
||||
$this->helper = new IframeAvailabilityChecker($this->translator);
|
||||
}
|
||||
|
||||
public function testCheckProtocolMismatch(): void
|
||||
{
|
||||
$currentScheme = 'https';
|
||||
$url = 'http://google.com'; // NOSONAR
|
||||
$translatedErrorMessage = 'error';
|
||||
$expectedResponseContent = [
|
||||
'status' => 0,
|
||||
'errorMessage' => $translatedErrorMessage,
|
||||
];
|
||||
|
||||
$this->translator->expects($this->once())
|
||||
->method('trans')
|
||||
->with(
|
||||
'mautic.focus.protocol.mismatch',
|
||||
[
|
||||
'%url%' => str_replace('http://', 'https://', $url),
|
||||
]
|
||||
)
|
||||
->willReturn($translatedErrorMessage);
|
||||
|
||||
/** @var JsonResponse $response */
|
||||
$response = $this->helper->check($url, $currentScheme);
|
||||
|
||||
$responseBody = json_decode($response->getContent(), true);
|
||||
$this->assertEquals($expectedResponseContent, $responseBody);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace MauticPlugin\MauticFocusBundle\Tests\Helper;
|
||||
|
||||
use Mautic\CoreBundle\Security\Permissions\CorePermissions;
|
||||
use MauticPlugin\MauticFocusBundle\Entity\Focus;
|
||||
use MauticPlugin\MauticFocusBundle\Helper\TokenHelper;
|
||||
use MauticPlugin\MauticFocusBundle\Model\FocusModel;
|
||||
use PHPUnit\Framework\MockObject\MockObject;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Symfony\Component\Routing\RouterInterface;
|
||||
|
||||
class TokenHelperTest extends TestCase
|
||||
{
|
||||
/**
|
||||
* @var FocusModel|MockObject
|
||||
*/
|
||||
private MockObject $model;
|
||||
|
||||
/**
|
||||
* @var MockObject|RouterInterface
|
||||
*/
|
||||
private MockObject $router;
|
||||
|
||||
/**
|
||||
* @var CorePermissions|MockObject
|
||||
*/
|
||||
private MockObject $security;
|
||||
|
||||
private TokenHelper $helper;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->model = $this->createMock(FocusModel::class);
|
||||
$this->router = $this->createMock(RouterInterface::class);
|
||||
$this->security = $this->createMock(CorePermissions::class);
|
||||
|
||||
$this->helper = new TokenHelper($this->model, $this->router, $this->security);
|
||||
}
|
||||
|
||||
public function testFindFocusTokensNotFound(): void
|
||||
{
|
||||
$content = 'content';
|
||||
|
||||
self::assertSame([], $this->helper->findFocusTokens($content));
|
||||
}
|
||||
|
||||
public function testFindFocusTokensFound(): void
|
||||
{
|
||||
$content = 'content {focus=1}';
|
||||
|
||||
self::assertSame(['{focus=1}' => ''], $this->helper->findFocusTokens($content));
|
||||
}
|
||||
|
||||
public function testFindFocusTokensFoundAddScriptByFocusPublishedStatus(): void
|
||||
{
|
||||
$focusItemId = 1;
|
||||
$content = "content {focus=$focusItemId}";
|
||||
|
||||
$focusItem = new Focus();
|
||||
$focusItem->setIsPublished(true);
|
||||
|
||||
$this->model->expects(self::once())
|
||||
->method('getEntity')
|
||||
->with($focusItemId)
|
||||
->willReturn($focusItem);
|
||||
|
||||
self::assertSame(
|
||||
['{focus=1}' => '<script src="" type="text/javascript" charset="utf-8" async="async"></script>'],
|
||||
$this->helper->findFocusTokens($content)
|
||||
);
|
||||
}
|
||||
|
||||
public function testFindFocusTokensFoundAddScriptByAccessCheck(): void
|
||||
{
|
||||
$focusItemId = 1;
|
||||
$createdById = 2;
|
||||
$content = "content {focus=$focusItemId}";
|
||||
|
||||
$focusItem = new Focus();
|
||||
$focusItem->setIsPublished(false);
|
||||
$focusItem->setCreatedBy($createdById);
|
||||
|
||||
$this->model->expects(self::once())
|
||||
->method('getEntity')
|
||||
->with($focusItemId)
|
||||
->willReturn($focusItem);
|
||||
|
||||
$this->security->expects(self::once())
|
||||
->method('hasEntityAccess')
|
||||
->with(
|
||||
'focus:items:viewown',
|
||||
'focus:items:viewother',
|
||||
$focusItem->getCreatedBy()
|
||||
)
|
||||
->willReturn(true);
|
||||
|
||||
self::assertSame(
|
||||
['{focus=1}' => '<script src="" type="text/javascript" charset="utf-8" async="async"></script>'],
|
||||
$this->helper->findFocusTokens($content)
|
||||
);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user