feat: localize guest endpoints and caching
This commit is contained in:
66
tests/Feature/Api/Event/EventAchievementsLocaleTest.php
Normal file
66
tests/Feature/Api/Event/EventAchievementsLocaleTest.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Event;
|
||||
|
||||
use App\Models\Emotion;
|
||||
use App\Models\Event;
|
||||
use App\Models\Photo;
|
||||
use App\Models\Task;
|
||||
use App\Services\EventJoinTokenService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class EventAchievementsLocaleTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_achievements_endpoint_returns_locale_specific_payload(): void
|
||||
{
|
||||
config(['app.supported_locales' => ['de', 'en']]);
|
||||
|
||||
$event = Event::factory()->create([
|
||||
'status' => 'published',
|
||||
'default_locale' => 'de',
|
||||
]);
|
||||
|
||||
$token = app(EventJoinTokenService::class)
|
||||
->createToken($event, ['label' => 'achievements'])
|
||||
->plain_token;
|
||||
|
||||
$emotion = Emotion::factory()->create([
|
||||
'name' => ['de' => 'Freude', 'en' => 'Joy'],
|
||||
]);
|
||||
|
||||
$task = Task::factory()->create([
|
||||
'tenant_id' => $event->tenant_id,
|
||||
'title' => ['de' => 'Feuerring', 'en' => 'Fire Ring'],
|
||||
'description' => ['de' => 'DE Beschr', 'en' => 'EN Desc'],
|
||||
'example_text' => ['de' => 'DE Example', 'en' => 'EN Example'],
|
||||
]);
|
||||
|
||||
Photo::factory()->for($event)->create([
|
||||
'tenant_id' => $event->tenant_id,
|
||||
'task_id' => $task->id,
|
||||
'emotion_id' => $emotion->id,
|
||||
'likes_count' => 42,
|
||||
'guest_name' => 'LocaleTester',
|
||||
]);
|
||||
|
||||
$responseEn = $this->withHeaders(['X-Device-Id' => 'LocaleTester'])
|
||||
->getJson("/api/v1/events/{$token}/achievements?locale=en&guest_name=LocaleTester");
|
||||
|
||||
$responseEn->assertOk();
|
||||
$responseEn->assertHeader('X-Content-Locale', 'en');
|
||||
$responseEn->assertJsonPath('highlights.top_photo.task', 'Fire Ring');
|
||||
$responseEn->assertJsonPath('highlights.trending_emotion.name', 'Joy');
|
||||
|
||||
$etag = $responseEn->headers->get('ETag');
|
||||
$this->assertNotEmpty($etag);
|
||||
|
||||
$this->withHeaders([
|
||||
'X-Device-Id' => 'LocaleTester',
|
||||
'If-None-Match' => $etag,
|
||||
])->getJson("/api/v1/events/{$token}/achievements?locale=en&guest_name=LocaleTester")
|
||||
->assertStatus(304);
|
||||
}
|
||||
}
|
||||
74
tests/Feature/Api/Event/EventPhotosLocaleTest.php
Normal file
74
tests/Feature/Api/Event/EventPhotosLocaleTest.php
Normal file
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Event;
|
||||
|
||||
use App\Models\Emotion;
|
||||
use App\Models\Event;
|
||||
use App\Models\Photo;
|
||||
use App\Models\Task;
|
||||
use App\Services\EventJoinTokenService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class EventPhotosLocaleTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_photos_endpoint_localizes_task_titles(): void
|
||||
{
|
||||
config(['app.supported_locales' => ['de', 'en']]);
|
||||
|
||||
$event = Event::factory()->create([
|
||||
'status' => 'published',
|
||||
'default_locale' => 'de',
|
||||
]);
|
||||
|
||||
$token = app(EventJoinTokenService::class)
|
||||
->createToken($event, ['label' => 'gallery'])
|
||||
->plain_token;
|
||||
|
||||
$emotion = Emotion::factory()->create([
|
||||
'name' => ['de' => 'Freude', 'en' => 'Joy'],
|
||||
]);
|
||||
|
||||
$task = Task::factory()->create([
|
||||
'tenant_id' => $event->tenant_id,
|
||||
'title' => ['de' => 'Kussmoment', 'en' => 'Kiss Moment'],
|
||||
'description' => ['de' => 'DE', 'en' => 'EN'],
|
||||
'example_text' => ['de' => 'DE Example', 'en' => 'EN Example'],
|
||||
]);
|
||||
|
||||
Photo::factory()->for($event)->create([
|
||||
'tenant_id' => $event->tenant_id,
|
||||
'task_id' => $task->id,
|
||||
'emotion_id' => $emotion->id,
|
||||
'created_at' => now(),
|
||||
]);
|
||||
|
||||
$responseEn = $this->withHeaders(['X-Device-Id' => 'device-123'])
|
||||
->getJson("/api/v1/events/{$token}/photos?locale=en");
|
||||
|
||||
$responseEn->assertOk();
|
||||
$responseEn->assertHeader('X-Content-Locale', 'en');
|
||||
$responseEn->assertJsonFragment(['task_title' => 'Kiss Moment']);
|
||||
|
||||
$etag = $responseEn->headers->get('ETag');
|
||||
$this->assertNotEmpty($etag);
|
||||
|
||||
$responseDe = $this->withHeaders([
|
||||
'X-Device-Id' => 'device-123',
|
||||
'Accept-Language' => 'de-DE',
|
||||
])
|
||||
->getJson("/api/v1/events/{$token}/photos?locale=it");
|
||||
|
||||
$responseDe->assertOk();
|
||||
$responseDe->assertHeader('X-Content-Locale', 'de');
|
||||
$responseDe->assertJsonFragment(['task_title' => 'Kussmoment']);
|
||||
|
||||
$this->withHeaders([
|
||||
'X-Device-Id' => 'device-123',
|
||||
'If-None-Match' => $etag,
|
||||
])->getJson("/api/v1/events/{$token}/photos?locale=en")
|
||||
->assertStatus(304);
|
||||
}
|
||||
}
|
||||
98
tests/Feature/Api/Event/EventTasksLocaleTest.php
Normal file
98
tests/Feature/Api/Event/EventTasksLocaleTest.php
Normal file
@@ -0,0 +1,98 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Api\Event;
|
||||
|
||||
use App\Models\Emotion;
|
||||
use App\Models\Event;
|
||||
use App\Models\Task;
|
||||
use App\Models\TaskCollection;
|
||||
use App\Services\EventJoinTokenService;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Tests\TestCase;
|
||||
|
||||
class EventTasksLocaleTest extends TestCase
|
||||
{
|
||||
use RefreshDatabase;
|
||||
|
||||
public function test_it_returns_requested_locale_payload(): void
|
||||
{
|
||||
config(['app.supported_locales' => ['de', 'en']]);
|
||||
|
||||
$event = Event::factory()->create([
|
||||
'default_locale' => 'de',
|
||||
'status' => 'published',
|
||||
]);
|
||||
$token = app(EventJoinTokenService::class)->createToken($event, ['label' => 'test']);
|
||||
$plainToken = $token->plain_token;
|
||||
|
||||
$emotion = Emotion::factory()->create([
|
||||
'name' => ['de' => 'Freude', 'en' => 'Joy'],
|
||||
]);
|
||||
|
||||
$task = Task::factory()->create([
|
||||
'tenant_id' => $event->tenant_id,
|
||||
'title' => ['de' => 'Kussmoment', 'en' => 'Kiss Moment'],
|
||||
'description' => ['de' => 'DE Beschreibung', 'en' => 'EN Description'],
|
||||
'example_text' => ['de' => 'DE Anleitung', 'en' => 'EN Instructions'],
|
||||
'emotion_id' => $emotion->id,
|
||||
]);
|
||||
|
||||
$collection = TaskCollection::factory()->create([
|
||||
'tenant_id' => $event->tenant_id,
|
||||
]);
|
||||
|
||||
$collection->tasks()->attach($task->id, ['sort_order' => 1]);
|
||||
$collection->events()->attach($event->id, ['sort_order' => 1]);
|
||||
|
||||
$response = $this->getJson("/api/v1/events/{$plainToken}/tasks?locale=en");
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertHeader('X-Content-Locale', 'en');
|
||||
$response->assertJsonCount(1);
|
||||
$response->assertJson([[
|
||||
'id' => $task->id,
|
||||
'title' => 'Kiss Moment',
|
||||
'description' => 'EN Description',
|
||||
'instructions' => 'EN Instructions',
|
||||
'duration' => 3,
|
||||
'is_completed' => false,
|
||||
]]);
|
||||
|
||||
$this->assertSame('emotion-'.$emotion->id, $response->json('0.emotion.slug'));
|
||||
}
|
||||
|
||||
public function test_it_falls_back_to_event_locale_when_locale_invalid(): void
|
||||
{
|
||||
config(['app.supported_locales' => ['de', 'en']]);
|
||||
|
||||
$event = Event::factory()->create([
|
||||
'default_locale' => 'de',
|
||||
'status' => 'published',
|
||||
]);
|
||||
$token = app(EventJoinTokenService::class)->createToken($event, ['label' => 'fallback']);
|
||||
$plainToken = $token->plain_token;
|
||||
|
||||
$task = Task::factory()->create([
|
||||
'tenant_id' => $event->tenant_id,
|
||||
'title' => ['de' => 'Aufgabe', 'en' => 'Task'],
|
||||
'description' => ['de' => 'Beschreibung', 'en' => 'Description'],
|
||||
'example_text' => ['de' => 'Beispiel', 'en' => 'Example'],
|
||||
]);
|
||||
|
||||
$collection = TaskCollection::factory()->create([
|
||||
'tenant_id' => $event->tenant_id,
|
||||
]);
|
||||
|
||||
$collection->tasks()->attach($task->id, ['sort_order' => 1]);
|
||||
$collection->events()->attach($event->id, ['sort_order' => 1]);
|
||||
|
||||
$response = $this->withHeaders(['Accept-Language' => 'zz-ZZ'])
|
||||
->getJson("/api/v1/events/{$plainToken}/tasks?locale=it");
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertHeader('X-Content-Locale', 'de');
|
||||
$response->assertJson([[
|
||||
'title' => 'Aufgabe',
|
||||
]]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user