update([ 'hero_title' => 'Celebrações com propósito', 'hero_cta_label' => 'Solicitar orçamento', 'manifesto_title' => 'Manifesto Amare', ]); Service::factory()->create([ 'title' => 'Serviço Rascunho', 'is_featured' => true, 'published_at' => null, ]); Service::factory()->published()->featured()->create([ 'title' => 'Serviço B', 'sort_order' => 20, ]); Service::factory()->published()->featured()->create([ 'title' => 'Serviço A', 'sort_order' => 10, ]); PortfolioCase::factory()->create([ 'title' => 'Caso Rascunho', 'is_featured' => true, 'published_at' => null, ]); PortfolioCase::factory()->published()->create([ 'title' => 'Caso B', 'is_featured' => true, 'sort_order' => 20, ]); PortfolioCase::factory()->published()->create([ 'title' => 'Caso A', 'is_featured' => true, 'sort_order' => 10, ]); Testimonial::factory()->create([ 'author_name' => 'Autor Rascunho', 'published_at' => null, ]); Testimonial::factory()->published()->create([ 'author_name' => 'Autor B', 'quote' => 'Depoimento B', 'sort_order' => 20, ]); Testimonial::factory()->published()->create([ 'author_name' => 'Autor A', 'quote' => 'Depoimento A', 'sort_order' => 10, ]); $response = $this->get(route('home')); $response ->assertOk() ->assertSee('Celebrações com propósito') ->assertSeeInOrder([ 'id="hero-heading"', 'id="manifesto-heading"', 'id="services-heading"', 'id="portfolio-heading"', 'id="method-heading"', 'id="testimonials-heading"', 'id="positioning-heading"', 'id="final-cta-heading"', ], false) ->assertSeeInOrder(['Serviço A', 'Serviço B']) ->assertSeeInOrder(['Caso A', 'Caso B']) ->assertSeeInOrder(['Autor A', 'Autor B']) ->assertDontSee('Serviço Rascunho') ->assertDontSee('Caso Rascunho') ->assertDontSee('Autor Rascunho') ->assertSee('data-testid="home-primary-cta"', false) ->assertSee('href="'.route('contact').'"', false); } public function test_empty_sections_are_omitted_when_no_published_content(): void { SiteSetting::instance(); $response = $this->get(route('home')); $response ->assertOk() ->assertDontSee('id="services-heading"', false) ->assertDontSee('id="portfolio-heading"', false) ->assertDontSee('id="testimonials-heading"', false) ->assertSee('id="manifesto-heading"', false) ->assertSee('id="method-heading"', false) ->assertSee('id="positioning-heading"', false) ->assertSee('id="final-cta-heading"', false); } public function test_hero_falls_back_to_default_copy_when_fields_are_empty(): void { SiteSetting::instance()->update([ 'hero_title' => '', 'hero_cta_label' => '', 'hero_secondary_cta_label' => '', 'hero_subtitle' => '', 'hero_note' => '', ]); $response = $this->get(route('home')); $response ->assertOk() ->assertSeeInOrder(['id="hero-heading"', 'Celebrações com propósito']) ->assertSeeInOrder(['data-testid="home-primary-cta"', 'Solicitar proposta']); } public function test_blank_quote_testimonials_are_skipped(): void { Testimonial::factory()->published()->create([ 'author_name' => 'Autor Mantido', 'quote' => 'Experiência impecável do início ao fim.', ]); Testimonial::factory()->published()->create([ 'author_name' => 'Autor Oculto', 'quote' => ' ', ]); $response = $this->get(route('home')); $response ->assertOk() ->assertSee('Autor Mantido') ->assertSee('Experiência impecável do início ao fim.') ->assertDontSee('Autor Oculto') ->assertSee('data-reveal-from="left"', false); } public function test_blank_testimonials_are_filtered_before_directional_sequence(): void { Testimonial::factory()->published()->create([ 'author_name' => 'Primeira autora', 'quote' => 'Primeiro relato.', 'sort_order' => 10, ]); Testimonial::factory()->published()->create([ 'author_name' => 'Relato vazio', 'quote' => " \n ", 'sort_order' => 20, ]); Testimonial::factory()->published()->create([ 'author_name' => 'Segunda autora', 'quote' => 'Segundo relato.', 'sort_order' => 30, ]); $response = $this->get(route('home')); $response ->assertOk() ->assertDontSee('Relato vazio') ->assertSeeInOrder([ 'data-reveal-from="left"', 'Primeira autora', 'data-reveal-from="right"', 'Segunda autora', ], false); $this->assertSame(1, substr_count($response->getContent(), 'data-reveal-from="left"')); $this->assertSame(1, substr_count($response->getContent(), 'data-reveal-from="right"')); } public function test_testimonials_section_is_omitted_when_every_published_quote_is_blank(): void { Testimonial::factory()->published()->create([ 'author_name' => 'Relato vazio', 'quote' => ' ', ]); $this->get(route('home')) ->assertOk() ->assertDontSee('id="testimonials-heading"', false) ->assertDontSee('href="#testimonials-heading"', false) ->assertDontSee('Relato vazio'); } public function test_home_folios_follow_rendered_chapter_order_and_hide_decorative_numbers(): void { SiteSetting::instance(); Service::factory()->published()->featured()->create(); PortfolioCase::factory()->published()->create(['is_featured' => true]); Testimonial::factory()->published()->create(['quote' => 'Relato publicado.']); $html = $this->get(route('home'))->assertOk()->getContent(); $this->assertSame([ 'Capa', 'Manifesto', 'Serviços', 'Portfólio', 'Método', 'Depoimentos', 'A Amare', 'Próximo passo', ], $this->folioLabels((string) $html)); $this->assertSame(8, preg_match_all('/data-home-folio-number[^>]*aria-hidden="true"/i', (string) $html)); $this->assertSame(1, preg_match_all('/assertStringContainsString('counter-reset: home-chapter -1', $css); $this->assertStringContainsString('counter-increment: home-chapter', $css); $this->assertStringContainsString('counter(home-chapter, decimal-leading-zero)', $css); } public function test_home_folios_are_omitted_with_conditional_chapters_without_leaving_markup_gaps(): void { SiteSetting::instance(); $html = $this->get(route('home'))->assertOk()->getContent(); $this->assertSame([ 'Capa', 'Manifesto', 'Método', 'A Amare', 'Próximo passo', ], $this->folioLabels((string) $html)); $this->assertSame(5, preg_match_all('/data-home-folio-number[^>]*aria-hidden="true"/i', (string) $html)); } /** @return list */ private function folioLabels(string $html): array { preg_match_all( '/]*data-home-folio-label[^>]*>\s*([^<]+?)\s*<\/span>/is', $html, $matches, ); return array_values(array_map( static fn (string $label): string => trim(html_entity_decode($label)), $matches[1], )); } }