mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 16:19:19 +02:00
200 lines
6.5 KiB
PHP
200 lines
6.5 KiB
PHP
<?php
|
||
|
||
use PHPUnit\Framework\TestCase;
|
||
|
||
/**
|
||
* TfeControllerOgTest — Pure logic tests for TfeController::buildOgTags()
|
||
* and buildMetaDescription().
|
||
*
|
||
* These methods are protected; we use a thin subclass to expose them.
|
||
*/
|
||
class TfeControllerOgTest extends TestCase
|
||
{
|
||
/**
|
||
* Subclass that exposes protected methods for testing.
|
||
*/
|
||
private static function makeController(): object
|
||
{
|
||
return new class extends TfeController {
|
||
public function __construct()
|
||
{
|
||
// Skip parent constructor — we don't need DB for these pure methods
|
||
}
|
||
|
||
public function exposedBuildOgTags(array $data, int $thesisId, string $metaDescription): array
|
||
{
|
||
return $this->buildOgTags($data, $thesisId, $metaDescription);
|
||
}
|
||
|
||
public function exposedBuildMetaDescription(string $synopsis): string
|
||
{
|
||
return $this->buildMetaDescription($synopsis);
|
||
}
|
||
|
||
public function exposedResolveOgImage(array $files): string
|
||
{
|
||
return $this->resolveOgImage($files);
|
||
}
|
||
};
|
||
}
|
||
|
||
// ── buildOgTags() ─────────────────────────────────────────────────────────
|
||
|
||
public function testBuildOgTagsReturnsAllRequiredKeys(): void
|
||
{
|
||
$ctrl = self::makeController();
|
||
$data = [
|
||
'title' => 'My Thesis',
|
||
'authors' => 'Jane Doe',
|
||
'year' => '2024',
|
||
'files' => [],
|
||
];
|
||
|
||
$tags = $ctrl->exposedBuildOgTags($data, 42, 'A description');
|
||
|
||
$requiredKeys = ['type', 'title', 'description', 'url', 'image', 'image_alt', 'site_name', 'article_author', 'article_published_time'];
|
||
foreach ($requiredKeys as $key) {
|
||
$this->assertArrayHasKey($key, $tags);
|
||
$this->assertIsString($tags[$key]);
|
||
}
|
||
}
|
||
|
||
public function testBuildOgTagsTitleIncludesAuthors(): void
|
||
{
|
||
$ctrl = self::makeController();
|
||
$data = [
|
||
'title' => 'The Title',
|
||
'authors' => 'Author Name',
|
||
'year' => '2024',
|
||
'files' => [],
|
||
];
|
||
|
||
$tags = $ctrl->exposedBuildOgTags($data, 1, 'desc');
|
||
|
||
$this->assertStringContainsString('The Title – Author Name', $tags['title']);
|
||
|
||
// Without authors, just the title
|
||
$data['authors'] = '';
|
||
$tags2 = $ctrl->exposedBuildOgTags($data, 1, 'desc');
|
||
$this->assertSame('The Title', $tags2['title']);
|
||
}
|
||
|
||
public function testBuildOgTagsImageEmptyWhenNoFiles(): void
|
||
{
|
||
$ctrl = self::makeController();
|
||
$data = [
|
||
'title' => 'No Files',
|
||
'authors' => 'A',
|
||
'year' => '2023',
|
||
'files' => [],
|
||
];
|
||
|
||
$tags = $ctrl->exposedBuildOgTags($data, 5, 'desc');
|
||
$this->assertSame('', $tags['image']);
|
||
}
|
||
|
||
public function testBuildOgTagsImageFromCover(): void
|
||
{
|
||
$ctrl = self::makeController();
|
||
$data = [
|
||
'title' => 'Cover Test',
|
||
'authors' => 'Author',
|
||
'year' => '2024',
|
||
'files' => [
|
||
['file_path' => 'documents/2024-001/cover.jpg', 'file_type' => 'cover'],
|
||
],
|
||
];
|
||
|
||
$tags = $ctrl->exposedBuildOgTags($data, 1, 'desc');
|
||
|
||
$this->assertStringContainsString('cover.jpg', $tags['image']);
|
||
}
|
||
|
||
public function testBuildOgTagsImageFallbackToFirstImage(): void
|
||
{
|
||
$ctrl = self::makeController();
|
||
$data = [
|
||
'title' => 'Image Test',
|
||
'authors' => 'B',
|
||
'year' => '2024',
|
||
'files' => [
|
||
['file_path' => 'documents/2024-001/doc.pdf', 'file_type' => 'tfe'],
|
||
['file_path' => 'documents/2024-001/screenshot.png', 'file_type' => 'tfe'],
|
||
],
|
||
];
|
||
|
||
$tags = $ctrl->exposedBuildOgTags($data, 2, 'desc');
|
||
|
||
$this->assertStringContainsString('screenshot.png', $tags['image']);
|
||
}
|
||
|
||
public function testBuildOgTagsUrlIncludesThesisId(): void
|
||
{
|
||
$ctrl = self::makeController();
|
||
$data = ['title' => 'URL Test', 'authors' => '', 'year' => '2024', 'files' => []];
|
||
|
||
$tags = $ctrl->exposedBuildOgTags($data, 99, 'desc');
|
||
|
||
$this->assertStringContainsString('tfe?id=99', $tags['url']);
|
||
}
|
||
|
||
public function testBuildOgTagsPublishedTimeFormatted(): void
|
||
{
|
||
$ctrl = self::makeController();
|
||
$data = ['title' => 'T', 'authors' => '', 'year' => '2025', 'files' => []];
|
||
|
||
$tags = $ctrl->exposedBuildOgTags($data, 1, 'desc');
|
||
|
||
$this->assertSame('2025-01-01', $tags['article_published_time']);
|
||
}
|
||
|
||
public function testBuildOgTagsPublishedTimeEmptyWhenNoYear(): void
|
||
{
|
||
$ctrl = self::makeController();
|
||
$data = ['title' => 'T', 'authors' => '', 'files' => []];
|
||
|
||
$tags = $ctrl->exposedBuildOgTags($data, 1, 'desc');
|
||
|
||
$this->assertSame('', $tags['article_published_time']);
|
||
}
|
||
|
||
// ── buildMetaDescription() ────────────────────────────────────────────────
|
||
|
||
public function testBuildMetaDescriptionTruncatesLongSynopsis(): void
|
||
{
|
||
$ctrl = self::makeController();
|
||
$long = str_repeat('abcdefghij', 20); // 200 chars
|
||
$desc = $ctrl->exposedBuildMetaDescription($long);
|
||
|
||
$this->assertLessThanOrEqual(160, strlen($desc));
|
||
$this->assertStringEndsWith('…', $desc);
|
||
}
|
||
|
||
public function testBuildMetaDescriptionKeepsShortSynopsis(): void
|
||
{
|
||
$ctrl = self::makeController();
|
||
$desc = $ctrl->exposedBuildMetaDescription('A short synopsis.');
|
||
|
||
$this->assertSame('A short synopsis.', $desc);
|
||
}
|
||
|
||
public function testBuildMetaDescriptionEmptySynopsisReturnsDefault(): void
|
||
{
|
||
$ctrl = self::makeController();
|
||
$desc = $ctrl->exposedBuildMetaDescription('');
|
||
|
||
$this->assertStringContainsString('Mémoire', $desc);
|
||
$this->assertStringContainsString('XAMXAM', $desc);
|
||
}
|
||
|
||
public function testBuildMetaDescriptionStripsHtmlTags(): void
|
||
{
|
||
$ctrl = self::makeController();
|
||
$desc = $ctrl->exposedBuildMetaDescription('<p>Hello <b>world</b></p>');
|
||
|
||
$this->assertStringNotContainsString('<p>', $desc);
|
||
$this->assertStringNotContainsString('<b>', $desc);
|
||
$this->assertStringContainsString('Hello world', $desc);
|
||
}
|
||
}
|