Files
amare/tests/Feature/Marketing/TestimonialsTest.php
Manoel Freitas 27711ad0c2 feat: add production testimonials seeder (#11)
Canonical upsert for five authorized couples so staging/prod
can load depoimentos without DatabaseSeeder/ContentSeeder.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-05 20:11:33 -03:00

277 lines
11 KiB
PHP

<?php
declare(strict_types=1);
namespace Tests\Feature\Marketing;
use App\Filament\Resources\Testimonials\Pages\ListTestimonials;
use App\Models\SiteSetting;
use App\Models\Testimonial;
use App\Models\User;
use Database\Seeders\ContentSeeder;
use Database\Seeders\TestimonialsSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Storage;
use Livewire\Livewire;
use Tests\TestCase;
class TestimonialsTest extends TestCase
{
use RefreshDatabase;
/**
* @var list<array{
* quote: string,
* author_name: string,
* context: string,
* sort_order: int,
* is_featured: bool,
* published_at: string
* }>
*/
private const EXPECTED_TESTIMONIALS = [
[
'quote' => "Mi, quero agradecer você e a sua equipe por todo empenho, atenção, vocês são abençoadas.\n\nEra nítida sua preocupação em garantir que todos os detalhes planejados desta comemoração, fossem atendidos.\n\nQue você possa transformar o grande dia das noivinhas sempre com essa sua leveza!!!\n\nMuito obrigada!",
'author_name' => 'Jeniffer e Maick',
'context' => 'Casamento · 06/12/2025',
'sort_order' => 1,
'is_featured' => true,
'published_at' => '2026-08-05 00:00:00',
],
[
'quote' => "Mi, eu não tenho palavras pra agradecer você e tudo que você fez por mim e por nós na realização desse sonho. Eu tô ainda extasiada com tudo que aconteceu hoje; mas tenho certeza que sem a sua ajuda, muita coisa não aconteceria.\n\nObrigada por tudo !",
'author_name' => 'Quesia e Jhonata',
'context' => 'Casamento · 21/12/2025',
'sort_order' => 2,
'is_featured' => true,
'published_at' => '2026-08-05 00:00:00',
],
[
'quote' => 'Que equipe!! Que equipe maravilhosa!! Obrigado pelo empenho de fazer tudo como eu queria!! Obrigado por se esforçar tanto e vir de tão longe pra realizar meu sonho!! Incríveis!!',
'author_name' => 'Milena e Weslley',
'context' => 'Casamento · 13/02/2026',
'sort_order' => 3,
'is_featured' => false,
'published_at' => '2026-08-05 00:00:00',
],
[
'quote' => "Gostaríamos de agradecer por todo o acompanhamento e dedicação durante a realização do nosso casamento. Foi um dia muito especial e inesquecível para nós.\n\nDesde o início, conseguimos conduzir tudo aquilo que estávamos planejando, dentro dos horários que estipulamos, o que foi ótimo, e no grande dia sua equipe nos recebeu e tratou com muito carinho, atenção e cuidado, o que fez toda a diferença para vivermos esse momento com mais tranquilidade.\n\nTambém adoramos as sugestões e ideias para as fotos, que deixaram os registros ainda mais bonitos e espontâneos, porque não iríamos lembrar de quais poses fazer na hora.\n\nObrigada por fazer parte de um momento tão importante das nossas vidas. Desejamos muito sucesso e que muitos outros casais possam viver dias especiais através do trabalho da AMARE.",
'author_name' => 'Raquel e Pedro',
'context' => 'Casamento · 09/05/2026',
'sort_order' => 4,
'is_featured' => false,
'published_at' => '2026-08-05 00:00:00',
],
[
'quote' => "Miiii, meu amor… você e sua equipe foram impecáveis.\n\nSuperou todas as nossas expectativas. Somos eternamente gratos por fazer nosso dia acontecer muito melhor do que imaginávamos.\n\nSempre muito atenciosa e paciente.\n\nAdoramos te conhecer e estamos muito felizes em termos escolhido você para assessorar nosso dia.",
'author_name' => 'Victoria e Pedro',
'context' => 'Casamento · 24/06/2026',
'sort_order' => 5,
'is_featured' => false,
'published_at' => '2026-08-05 00:00:00',
],
];
public function test_published_scope_excludes_unpublished_testimonials(): void
{
Testimonial::factory()->create(['published_at' => null]);
$published = Testimonial::factory()->published()->create();
$this->assertCount(1, Testimonial::query()->published()->get());
$this->assertTrue(Testimonial::query()->published()->first()?->is($published));
}
public function test_featured_testimonials_are_filterable(): void
{
Testimonial::factory()->create(['is_featured' => false]);
$featured = Testimonial::factory()->featured()->create();
$results = Testimonial::query()->where('is_featured', true)->get();
$this->assertCount(1, $results);
$this->assertTrue($results->first()?->is($featured));
}
public function test_assistant_cannot_access_testimonials_resource(): void
{
$assistant = User::factory()->assistant()->create();
$this->actingAs($assistant);
Livewire::test(ListTestimonials::class)
->assertForbidden();
}
public function test_testimonials_seeder_maps_all_five_real_couples_from_depoimentos(): void
{
$this->runTestimonialsSeeder();
$testimonials = Testimonial::query()
->orderBy('sort_order')
->get()
->map(fn (Testimonial $testimonial): array => $this->sourceOwnedState($testimonial))
->all();
$this->assertSame(self::EXPECTED_TESTIMONIALS, $testimonials);
}
public function test_content_seeder_loads_five_real_couples_from_depoimentos(): void
{
Storage::fake('public');
$this->artisan('db:seed', [
'--class' => ContentSeeder::class,
'--no-interaction' => true,
])->assertExitCode(0);
$authors = Testimonial::query()->orderBy('sort_order')->pluck('author_name')->all();
$this->assertSame([
'Jeniffer e Maick',
'Quesia e Jhonata',
'Milena e Weslley',
'Raquel e Pedro',
'Victoria e Pedro',
], $authors);
$jeniffer = Testimonial::query()->where('author_name', 'Jeniffer e Maick')->first();
$this->assertNotNull($jeniffer);
$this->assertStringContainsString('Mi, quero agradecer', (string) $jeniffer->quote);
$this->assertStringContainsString("\n\n", (string) $jeniffer->quote);
$this->assertSame('Casamento · 06/12/2025', $jeniffer->context);
}
public function test_testimonials_seeder_authoritatively_overwrites_source_owned_fields(): void
{
$testimonial = Testimonial::factory()->create([
'quote' => 'Depoimento desatualizado.',
'author_name' => 'Jeniffer e Maick',
'context' => 'Contexto desatualizado',
'sort_order' => 99,
'is_featured' => false,
'published_at' => null,
]);
$this->runTestimonialsSeeder();
$this->assertSame(
self::EXPECTED_TESTIMONIALS[0],
$this->sourceOwnedState($testimonial->refresh()),
);
}
public function test_testimonials_seeder_preserves_curated_photo_fields_for_known_author(): void
{
$testimonial = Testimonial::factory()->create([
'author_name' => 'Jeniffer e Maick',
'photo_path' => 'testimonials/jeniffer-e-maick.jpg',
'photo_alt' => 'Jeniffer e Maick durante o casamento',
]);
$this->runTestimonialsSeeder();
$testimonial->refresh();
$this->assertSame('testimonials/jeniffer-e-maick.jpg', $testimonial->photo_path);
$this->assertSame('Jeniffer e Maick durante o casamento', $testimonial->photo_alt);
}
public function test_testimonials_seeder_leaves_unrelated_testimonials_unchanged(): void
{
$unrelated = Testimonial::factory()->published()->featured()->create([
'quote' => 'Depoimento cadastrado pela equipe.',
'author_name' => 'Casal não presente na fonte',
'context' => 'Bodas · 02/08/2026',
'photo_path' => 'testimonials/casal-equipe.jpg',
'photo_alt' => 'Casal cadastrado pela equipe',
'sort_order' => 42,
]);
$originalState = $unrelated->getAttributes();
ksort($originalState);
$this->runTestimonialsSeeder();
$persisted = $unrelated->fresh();
$this->assertNotNull($persisted);
$persistedState = $persisted->getAttributes();
ksort($persistedState);
$this->assertSame($originalState, $persistedState);
}
public function test_testimonials_seeder_is_idempotent_without_duplicate_authors(): void
{
$this->runTestimonialsSeeder();
$firstRunState = Testimonial::query()
->orderBy('id')
->get()
->map(fn (Testimonial $testimonial): array => $testimonial->getAttributes())
->all();
$this->runTestimonialsSeeder();
$secondRunState = Testimonial::query()
->orderBy('id')
->get()
->map(fn (Testimonial $testimonial): array => $testimonial->getAttributes())
->all();
$this->assertCount(5, $secondRunState);
$this->assertSame($firstRunState, $secondRunState);
$this->assertSame(5, Testimonial::query()->distinct()->count('author_name'));
}
public function test_home_renders_multi_paragraph_testimonial_quotes(): void
{
SiteSetting::instance();
Testimonial::factory()->published()->featured()->create([
'quote' => "Primeiro parágrafo do depoimento.\n\nSegundo parágrafo com continuidade.",
'author_name' => 'Casal Exemplo',
'context' => 'Casamento · 01/01/2026',
]);
$response = $this->get(route('home'));
$response->assertOk();
$response->assertSee('Primeiro parágrafo do depoimento.', false);
$response->assertSee('Segundo parágrafo com continuidade.', false);
$response->assertDontSee(
'Primeiro parágrafo do depoimento. Segundo parágrafo com continuidade.',
false,
);
}
private function runTestimonialsSeeder(): void
{
$this->artisan('db:seed', [
'--class' => TestimonialsSeeder::class,
'--no-interaction' => true,
])->assertExitCode(0);
}
/**
* @return array{
* quote: string,
* author_name: string,
* context: string,
* sort_order: int,
* is_featured: bool,
* published_at: string
* }
*/
private function sourceOwnedState(Testimonial $testimonial): array
{
return [
'quote' => (string) $testimonial->quote,
'author_name' => (string) $testimonial->author_name,
'context' => (string) $testimonial->context,
'sort_order' => (int) $testimonial->sort_order,
'is_featured' => (bool) $testimonial->is_featured,
'published_at' => $testimonial->published_at?->format('Y-m-d H:i:s') ?? '',
];
}
}