6d71f5fecf
syncLinks parses the default-locale content; processLinks resolves each [[link]] against the current locale at render time. Link labels preserve original spelling; destination resolves to the same document in the current locale (with fallback).
146 lines
5.3 KiB
PHP
146 lines
5.3 KiB
PHP
<?php
|
|
|
|
namespace Tests\Unit\Models;
|
|
|
|
use App\Models\Document;
|
|
use App\Models\DocumentTranslation;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\App;
|
|
use Tests\TestCase;
|
|
|
|
class DocumentTest extends TestCase
|
|
{
|
|
use RefreshDatabase;
|
|
|
|
public function test_title_accessor_returns_current_locale_translation(): void
|
|
{
|
|
$doc = Document::factory()->create(['default_locale' => 'en']);
|
|
$doc->translations()->where('locale', 'en')->update(['title' => 'Hello']);
|
|
DocumentTranslation::factory()->create([
|
|
'document_id' => $doc->id,
|
|
'locale' => 'ja',
|
|
'title' => 'こんにちは',
|
|
]);
|
|
|
|
App::setLocale('ja');
|
|
$this->assertSame('こんにちは', $doc->fresh()->title);
|
|
|
|
App::setLocale('en');
|
|
$this->assertSame('Hello', $doc->fresh()->title);
|
|
}
|
|
|
|
public function test_title_accessor_falls_back_to_default_locale(): void
|
|
{
|
|
$doc = Document::factory()->create(['default_locale' => 'en']);
|
|
$doc->translations()->where('locale', 'en')->update(['title' => 'Hello']);
|
|
|
|
App::setLocale('ja');
|
|
$this->assertSame('Hello', $doc->fresh()->title);
|
|
}
|
|
|
|
public function test_content_and_rendered_html_accessors_fall_back(): void
|
|
{
|
|
$doc = Document::factory()->create(['default_locale' => 'en']);
|
|
$doc->translations()->where('locale', 'en')->update([
|
|
'content' => 'English body',
|
|
'rendered_html' => '<p>English body</p>',
|
|
]);
|
|
|
|
App::setLocale('ja');
|
|
$fresh = $doc->fresh();
|
|
$this->assertSame('English body', $fresh->content);
|
|
$this->assertSame('<p>English body</p>', $fresh->rendered_html);
|
|
}
|
|
|
|
public function test_is_fallback_returns_true_when_locale_missing(): void
|
|
{
|
|
$doc = Document::factory()->create(['default_locale' => 'en']);
|
|
$this->assertTrue($doc->isFallback('ja'));
|
|
$this->assertFalse($doc->isFallback('en'));
|
|
}
|
|
|
|
public function test_translation_for_returns_null_when_fallback_disabled(): void
|
|
{
|
|
$doc = Document::factory()->create(['default_locale' => 'en']);
|
|
$this->assertNull($doc->translationFor('ja', fallback: false));
|
|
$this->assertNotNull($doc->translationFor('ja', fallback: true));
|
|
}
|
|
|
|
public function test_available_locales_lists_existing_translations(): void
|
|
{
|
|
$doc = Document::factory()->create(['default_locale' => 'en']);
|
|
DocumentTranslation::factory()->create(['document_id' => $doc->id, 'locale' => 'ja']);
|
|
DocumentTranslation::factory()->create(['document_id' => $doc->id, 'locale' => 'fr']);
|
|
|
|
$locales = $doc->fresh()->availableLocales();
|
|
sort($locales);
|
|
$this->assertSame(['en', 'fr', 'ja'], $locales);
|
|
}
|
|
|
|
public function test_sync_links_creates_outgoing_links_with_resolved_targets(): void
|
|
{
|
|
$target = Document::factory()->create(['default_locale' => 'en']);
|
|
$target->translations()->where('locale', 'en')->update(['title' => 'Target']);
|
|
|
|
$source = Document::factory()->create(['default_locale' => 'en']);
|
|
$source->translations()->where('locale', 'en')->update([
|
|
'content' => 'See [[Target]] for details.',
|
|
]);
|
|
|
|
$source->fresh('translations')->syncLinks();
|
|
|
|
$links = $source->fresh()->outgoingLinks;
|
|
$this->assertCount(1, $links);
|
|
$this->assertSame($target->id, $links->first()->target_document_id);
|
|
$this->assertSame('Target', $links->first()->target_title);
|
|
}
|
|
|
|
public function test_sync_links_records_unresolved_links_with_null_target(): void
|
|
{
|
|
$source = Document::factory()->create();
|
|
$source->translations()->first()->update([
|
|
'content' => 'Goes to [[NoSuchPage]].',
|
|
]);
|
|
|
|
$source->fresh('translations')->syncLinks();
|
|
|
|
$links = $source->fresh()->outgoingLinks;
|
|
$this->assertCount(1, $links);
|
|
$this->assertNull($links->first()->target_document_id);
|
|
}
|
|
|
|
public function test_process_links_replaces_wiki_link_with_anchor_keeping_label(): void
|
|
{
|
|
$target = Document::factory()->create(['default_locale' => 'en', 'slug' => 'target-doc']);
|
|
$target->translations()->where('locale', 'en')->update(['title' => 'Target']);
|
|
\Illuminate\Support\Facades\App::setLocale('ja');
|
|
\App\Models\DocumentTranslation::factory()->create([
|
|
'document_id' => $target->id,
|
|
'locale' => 'ja',
|
|
'title' => 'ターゲット',
|
|
]);
|
|
|
|
$source = Document::factory()->create();
|
|
$source->translations()->first()->update([
|
|
'rendered_html' => '<p>See [[Target]].</p>',
|
|
]);
|
|
|
|
$html = $source->fresh()->processLinks();
|
|
|
|
$this->assertStringContainsString('href="' . route('documents.show', 'target-doc') . '"', $html);
|
|
$this->assertStringContainsString('>Target<', $html); // label preserved
|
|
$this->assertStringContainsString('class="wiki-link"', $html);
|
|
}
|
|
|
|
public function test_process_links_marks_unresolved_links_as_new(): void
|
|
{
|
|
$source = Document::factory()->create();
|
|
$source->translations()->first()->update([
|
|
'rendered_html' => '<p>Click [[Ghost]].</p>',
|
|
]);
|
|
|
|
$html = $source->fresh()->processLinks();
|
|
$this->assertStringContainsString('wiki-link-new', $html);
|
|
}
|
|
}
|