File: /home/xedaptot/be.naniguide.com/tests/Unit/TagTranslationServiceTest.php
<?php
namespace Tests\Unit;
use Tests\TestCase;
use App\Services\TagTranslationService;
use App\Library\Contracts\TagResolverInterface;
use App\Model\Subscriber;
class TagTranslationServiceTest extends TestCase
{
public function test_it_translates_tags_using_resolvers()
{
// Resolve via service container
$service = app(TagTranslationService::class);
$resolver = new class implements TagResolverInterface {
public function getResolvedTags(): array
{
return [
'name' => 'Alice',
'email' => '[email protected]',
];
}
};
$input = 'Hello {{ name }}, your email is {{ email }}.';
$expected = 'Hello Alice, your email is [email protected].';
$result = $service->translate($input, $resolver);
$this->assertEquals($expected, $result);
}
public function test_it_ignores_missing_tags()
{
$service = app(TagTranslationService::class);
$resolver = new class implements TagResolverInterface {
public function getResolvedTags(): array
{
return ['name' => 'Bob'];
}
};
$input = 'Hi {{ name }}, your age is {{ age }}.';
$expected = 'Hi Bob, your age is .'; // Twig leaves missing tags blank
$result = $service->translate($input, $resolver);
$this->assertEquals($expected, $result);
}
public function test_it_combines_multiple_resolvers()
{
$service = app(TagTranslationService::class);
$resolverA = new class implements TagResolverInterface {
public function getResolvedTags(): array
{
return ['name' => 'Charlie'];
}
};
$resolverB = new class implements TagResolverInterface {
public function getResolvedTags(): array
{
return ['city' => 'Paris'];
}
};
$input = 'Hello {{ name }} from {{ city }}!';
$expected = 'Hello Charlie from Paris!';
$result = $service->translate($input, $resolverA, $resolverB);
$this->assertEquals($expected, $result);
}
public function test_with_a_domain_object_resolver_also_support_tags_flattening()
{
$service = app(TagTranslationService::class);
$mailList = new \App\Model\MailList([
'name' => 'Weekly Updates!'
]);
$mailList->uid = '1000000000'; // UID is not fillable, explicitly assign
$testCases = [
'Hello "{{ list.name }}"' => 'Hello "Weekly Updates!"',
'Hello "{{ list_name }}"' => 'Hello "Weekly Updates!"',
'Hello "{{ LIST_NAME }}"' => 'Hello "Weekly Updates!"',
'Hello "{{ LIST.NAME }}", My UID is {{ LIST_UID }}"' => 'Hello "Weekly Updates!", My UID is 1000000000"',
'{{ LIST.NAME }} {{ LIST.UID }} {{ LIST_NAME }} {{ LIST.UID }}' => 'Weekly Updates! 1000000000 Weekly Updates! 1000000000',
'{{List.Name}} is invalid' => ' is invalid', // empty, no exception thrown
];
foreach ($testCases as $input => $expectedTesult) {
$result = $service->translate($input, $mailList);
$this->assertEquals($result, $expectedTesult);
}
}
public function test_advanced_subscriber_tag_resolver()
{
// Create a Subscriber mock with intrinsic tags
$subscriber = new class extends \App\Model\Subscriber {
public int $id = 123;
public \App\Model\MailList $mailList;
public function __construct()
{
$this->mailList = new class extends \App\Model\MailList {
public string $uid = 'list-uid-456';
public \App\Model\Customer $customer;
public function __construct()
{
$this->customer = new class extends \App\Model\Customer {
public string $uid = 'customer-uid-789';
};
}
};
}
public function getResolvedTags(): array
{
return [
'SUBSCRIBER_UID' => $this->id,
'SUBSCRIBER_EMAIL' => '[email protected]',
];
}
public function generateUnsubscribeFormUrl(?string $messageId, bool $useAbsoluteUrl = true): string
{
return $messageId ? "unsubscribe/{$messageId}" : "unsubscribe/default";
}
public function generateUpdateProfileUrl(): string
{
return "update-profile/{$this->id}";
}
};
$messageId = 'MSG123';
// Instantiate the advanced resolver using the factory method
$resolver = \App\Library\AdvancedSubscriberTagResolver::for($subscriber, $messageId);
$tags = $resolver->getResolvedTags();
// Assert that intrinsic subscriber tags are preserved
$this->assertArrayHasKey('SUBSCRIBER_UID', $tags);
$this->assertArrayHasKey('SUBSCRIBER_EMAIL', $tags);
$this->assertEquals(123, $tags['SUBSCRIBER_UID']);
$this->assertEquals('[email protected]', $tags['SUBSCRIBER_EMAIL']);
// Assert that advanced tags are added
$this->assertArrayHasKey('unsubscribe_url', $tags);
$this->assertArrayHasKey('update_profile_url', $tags);
$this->assertEquals('unsubscribe/MSG123', $tags['unsubscribe_url']);
$this->assertEquals('update-profile/123', $tags['update_profile_url']);
}
public function test_advanced_subscriber_tag_resolver_with_subscriber_fake_object()
{
// Create a Subscriber mock with intrinsic tags
$messageId = 'MSG123';
$subscriber = Subscriber::fake(
attributes: [
'email' => '[email protected]',
],
methods: [
'generateUnsubscribeFormUrl' => "unsubscribe/",
'generateUpdateProfileUrl' => "update-profile/",
'getResolvedTags' => [
'SUBSCRIBER_UID' => 123,
'SUBSCRIBER_EMAIL' => '[email protected]',
]
],
);
// Instantiate the advanced resolver using the factory method
$resolver = \App\Library\AdvancedSubscriberTagResolver::for($subscriber, $messageId, $withHost = false);
$tags = $resolver->getResolvedTags();
// Assert that intrinsic subscriber tags are preserved
$this->assertArrayHasKey('SUBSCRIBER_UID', $tags);
$this->assertArrayHasKey('SUBSCRIBER_EMAIL', $tags);
$this->assertEquals(123, $tags['SUBSCRIBER_UID']);
$this->assertEquals('[email protected]', $tags['SUBSCRIBER_EMAIL']);
// Assert that advanced tags are added
$this->assertArrayHasKey('unsubscribe_url', $tags);
$this->assertArrayHasKey('update_profile_url', $tags);
$this->assertEquals('unsubscribe/', $tags['unsubscribe_url']);
$this->assertEquals('update-profile/', $tags['update_profile_url']);
$this->assertEquals('/campaigns/TVNHMTIz/web-view', $tags['web_view_url']);
}
}