Saving a page with a category failed with "El campo categoría no está
en la lista de valores permitidos" — for every category, not only the
one being tried. Filament builds such a list through a query, which
handles `->relationship('category', 'name->es')`, but validates a choice
by reading the title back off the record as a property,
`$record->{'name->es'}`, which does not exist. No label, so every
option was refused.
The same pattern was in seven more places: a call's, a testimonial's,
a talk's and a repository's project, a testimonial's service, and the
page and application filters. TranslatedOptionLabel gives Filament the
record's own translation instead, in the language of whoever uses the
panel; the JSON path stays for search and ordering.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
95 lines
3.3 KiB
PHP
95 lines
3.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Feature\Panel;
|
|
|
|
use App\Filament\Resources\Calls\Pages\CreateCall;
|
|
use App\Filament\Resources\Pages\Pages\CreatePage;
|
|
use App\Filament\Resources\Repositories\Pages\CreateRepository;
|
|
use App\Filament\Resources\Talks\Pages\CreateTalk;
|
|
use App\Filament\Resources\Testimonials\Pages\CreateTestimonial;
|
|
use App\Models\Category;
|
|
use App\Models\Project;
|
|
use App\Models\Service;
|
|
use Database\Seeders\RolePermissionSeeder;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\Queue;
|
|
use Livewire\Livewire;
|
|
use PHPUnit\Framework\Attributes\DataProvider;
|
|
use PHPUnit\Framework\Attributes\Test;
|
|
use Tests\FakesPireon;
|
|
use Tests\TestCase;
|
|
|
|
/**
|
|
* A select whose options are records with a translatable title — a page's
|
|
* category, the project a call belongs to — must accept the option picked.
|
|
*
|
|
* It did not: every choice was refused as "not in the list of allowed
|
|
* values", because Filament validated it by reading `name->es` off the record
|
|
* as a property. See App\Filament\Support\TranslatedOptionLabel.
|
|
*/
|
|
class TranslatedRelationshipSelectsTest extends TestCase
|
|
{
|
|
use FakesPireon, RefreshDatabase;
|
|
|
|
protected function setUp(): void
|
|
{
|
|
parent::setUp();
|
|
|
|
$this->seed(RolePermissionSeeder::class);
|
|
Queue::fake();
|
|
|
|
$this->actingAs($this->userWithRoles('super_admin'));
|
|
}
|
|
|
|
/**
|
|
* @return array<string, array{0: class-string, 1: string, 2: string}>
|
|
*/
|
|
public static function selects(): array
|
|
{
|
|
return [
|
|
"a page's category" => [CreatePage::class, 'category_id', Category::class],
|
|
"a call's project" => [CreateCall::class, 'project_id', Project::class],
|
|
"a testimonial's project" => [CreateTestimonial::class, 'project_id', Project::class],
|
|
"a testimonial's service" => [CreateTestimonial::class, 'service_id', Service::class],
|
|
"a talk's project" => [CreateTalk::class, 'project_id', Project::class],
|
|
"a repository's project" => [CreateRepository::class, 'project_id', Project::class],
|
|
];
|
|
}
|
|
|
|
/**
|
|
* @param class-string $page
|
|
* @param class-string<Model> $model
|
|
*/
|
|
#[Test]
|
|
#[DataProvider('selects')]
|
|
public function the_option_picked_is_accepted(string $page, string $field, string $model): void
|
|
{
|
|
$record = $model::factory()->create();
|
|
|
|
// Only this field is asserted: the rest of each form is left empty on
|
|
// purpose, and its own errors are not what this is about.
|
|
Livewire::test($page)
|
|
->fillForm([$field => $record->getKey()])
|
|
->call('create')
|
|
->assertHasNoFormErrors([$field]);
|
|
}
|
|
|
|
#[Test]
|
|
public function the_option_reads_in_the_language_of_whoever_uses_the_panel(): void
|
|
{
|
|
$category = Category::factory()->create(['name' => ['es' => 'Novedades', 'en' => 'News']]);
|
|
|
|
app()->setLocale('en');
|
|
|
|
$select = collect(Livewire::test(CreatePage::class)->instance()->form->getFlatComponents())
|
|
->first(fn ($component) => method_exists($component, 'getName') && $component->getName() === 'category_id');
|
|
|
|
$label = $select->getOptionLabelFromRecord($category);
|
|
|
|
$this->assertSame('News', $label);
|
|
}
|
|
}
|