Make DocumentService locale-aware
createDocument/updateDocument now accept a \$locale parameter and write to document_translations. Adds addTranslation, deleteTranslation, setDefaultLocale (with path/slug regen), distinct-document search, and findByTitle that delegates to WikiLinkResolver.
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Unit\Services;
|
||||
|
||||
use App\Models\Document;
|
||||
use App\Models\DocumentTranslation;
|
||||
use App\Models\User;
|
||||
use App\Services\DocumentService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Tests\TestCase;
|
||||
|
||||
class DocumentServiceTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
private DocumentService $service;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
$this->service = new DocumentService();
|
||||
}
|
||||
|
||||
public function test_create_document_creates_one_translation_in_given_locale(): void
|
||||
{
|
||||
App::setLocale('en'); // ensure deterministic
|
||||
$user = User::factory()->create();
|
||||
|
||||
$doc = $this->service->createDocument('Hello', '# Hi', $user->id, 'en');
|
||||
|
||||
$this->assertSame('en', $doc->default_locale);
|
||||
$this->assertSame('Hello.md', $doc->path);
|
||||
$this->assertSame('hello', $doc->slug);
|
||||
$this->assertCount(1, $doc->translations);
|
||||
$this->assertSame('Hello', $doc->translations->first()->title);
|
||||
$this->assertSame('# Hi', $doc->translations->first()->content);
|
||||
$this->assertStringContainsString('<h1>', $doc->translations->first()->rendered_html);
|
||||
}
|
||||
|
||||
public function test_update_document_in_default_locale_regenerates_path_and_slug(): void
|
||||
{
|
||||
$doc = $this->service->createDocument('Old', 'body', null, 'en');
|
||||
|
||||
$updated = $this->service->updateDocument($doc, 'New Title', 'body2', null, 'en');
|
||||
|
||||
$this->assertSame('New Title.md', $updated->path);
|
||||
$this->assertSame('new-title', $updated->slug);
|
||||
}
|
||||
|
||||
public function test_update_document_in_non_default_locale_does_not_change_path(): void
|
||||
{
|
||||
$doc = $this->service->createDocument('English', 'body', null, 'en');
|
||||
$originalPath = $doc->path;
|
||||
$originalSlug = $doc->slug;
|
||||
|
||||
$updated = $this->service->updateDocument($doc, '日本語タイトル', '本文', null, 'ja');
|
||||
|
||||
$this->assertSame($originalPath, $updated->path);
|
||||
$this->assertSame($originalSlug, $updated->slug);
|
||||
$this->assertSame('日本語タイトル', $updated->translationFor('ja', false)->title);
|
||||
}
|
||||
|
||||
public function test_add_translation_creates_new_locale_row(): void
|
||||
{
|
||||
$doc = $this->service->createDocument('Hello', 'body', null, 'en');
|
||||
|
||||
$this->service->addTranslation($doc, 'ja', 'こんにちは', 'やあ', null);
|
||||
|
||||
$this->assertCount(2, $doc->fresh()->translations);
|
||||
$this->assertSame('こんにちは', $doc->fresh()->translationFor('ja', false)->title);
|
||||
}
|
||||
|
||||
public function test_add_translation_throws_on_duplicate_locale(): void
|
||||
{
|
||||
$doc = $this->service->createDocument('Hello', 'body', null, 'en');
|
||||
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->service->addTranslation($doc, 'en', 'X', 'Y', null);
|
||||
}
|
||||
|
||||
public function test_delete_translation_removes_non_default(): void
|
||||
{
|
||||
$doc = $this->service->createDocument('Hello', 'body', null, 'en');
|
||||
$this->service->addTranslation($doc, 'ja', 'こんにちは', 'やあ', null);
|
||||
|
||||
$this->service->deleteTranslation($doc, 'ja');
|
||||
|
||||
$this->assertNull($doc->fresh()->translationFor('ja', false));
|
||||
}
|
||||
|
||||
public function test_delete_translation_refuses_default_locale(): void
|
||||
{
|
||||
$doc = $this->service->createDocument('Hello', 'body', null, 'en');
|
||||
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->service->deleteTranslation($doc, 'en');
|
||||
}
|
||||
|
||||
public function test_set_default_locale_requires_existing_translation(): void
|
||||
{
|
||||
$doc = $this->service->createDocument('Hello', 'body', null, 'en');
|
||||
|
||||
$this->expectException(\InvalidArgumentException::class);
|
||||
$this->service->setDefaultLocale($doc, 'ja');
|
||||
}
|
||||
|
||||
public function test_set_default_locale_regenerates_path_from_new_locale_title(): void
|
||||
{
|
||||
$doc = $this->service->createDocument('Hello', 'body', null, 'en');
|
||||
$this->service->addTranslation($doc, 'ja', 'こんにちは', 'やあ', null);
|
||||
|
||||
$updated = $this->service->setDefaultLocale($doc, 'ja');
|
||||
|
||||
$this->assertSame('ja', $updated->default_locale);
|
||||
$this->assertSame('こんにちは.md', $updated->path);
|
||||
}
|
||||
|
||||
public function test_search_returns_distinct_documents_across_locales(): void
|
||||
{
|
||||
$doc = $this->service->createDocument('Searchword', 'body', null, 'en');
|
||||
$this->service->addTranslation($doc, 'ja', 'Searchword JA', 'Searchword body', null);
|
||||
|
||||
$results = $this->service->search('Searchword');
|
||||
|
||||
$this->assertCount(1, $results); // distinct, even though 2 translations match
|
||||
$this->assertSame($doc->id, $results->first()->id);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user