diff --git a/composer.json b/composer.json
index 99388c72..3cab6524 100644
--- a/composer.json
+++ b/composer.json
@@ -15,9 +15,23 @@
"php": ">=8.1"
},
"require-dev": {
+ "phpunit/phpunit": "^10.5",
"squizlabs/php_codesniffer": "^3.7",
"phpstan/phpstan": "^1.10",
- "joomla/coding-standards": "^4.0"
+ "joomla/coding-standards": "dev-3.x-dev"
+ },
+ "autoload": {
+ "psr-4": {
+ "Joomla\\Component\\MokoSuiteCross\\Administrator\\": "source/packages/com_mokosuitecross/src/",
+ "Joomla\\Component\\MokoSuiteCross\\Site\\": "source/packages/com_mokosuitecross/site/src/",
+ "Joomla\\Plugin\\Content\\MokoSuiteCross\\": "source/packages/plg_content_mokosuitecross/src/",
+ "Joomla\\Plugin\\System\\MokoSuiteCross\\": "source/packages/plg_system_mokosuitecross/src/"
+ }
+ },
+ "autoload-dev": {
+ "psr-4": {
+ "MokoSuiteCross\\Tests\\": "tests/"
+ }
},
"config": {
"sort-packages": true
diff --git a/phpunit.xml.dist b/phpunit.xml.dist
new file mode 100644
index 00000000..a8b7ba93
--- /dev/null
+++ b/phpunit.xml.dist
@@ -0,0 +1,22 @@
+
+
+
+
+ tests/Unit
+
+
+
+
+ source/packages/com_mokosuitecross/src
+ source/packages/plg_content_mokosuitecross/src
+ source/packages/plg_system_mokosuitecross/src
+
+
+
diff --git a/tests/Unit/Helper/PreviewHelperTest.php b/tests/Unit/Helper/PreviewHelperTest.php
new file mode 100644
index 00000000..7d3d8dfa
--- /dev/null
+++ b/tests/Unit/Helper/PreviewHelperTest.php
@@ -0,0 +1,128 @@
+
+ * @copyright Copyright (C) 2026 Moko Consulting. All rights reserved.
+ * @license GNU General Public License version 3 or later; see LICENSE
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+namespace MokoSuiteCross\Tests\Unit\Helper;
+
+use Joomla\Component\MokoSuiteCross\Administrator\Helper\PreviewHelper;
+use PHPUnit\Framework\Attributes\RequiresMethod;
+use PHPUnit\Framework\TestCase;
+
+#[RequiresMethod(PreviewHelper::class, 'render')]
+class PreviewHelperTest extends TestCase
+{
+ public function testRenderTwitterContainsCharCount(): void
+ {
+ $html = PreviewHelper::render('twitter', 'Test Title', 'Hello world', 'https://example.com', '', 'Author');
+
+ $this->assertStringContainsString('11/280', $html);
+ }
+
+ public function testRenderTwitterEscapesHtml(): void
+ {
+ $html = PreviewHelper::render('twitter', '', 'text', 'https://example.com');
+
+ $this->assertStringNotContainsString('