test: Serviços — cobertura da nova página e atualização da spec
This commit is contained in:
@@ -67,10 +67,13 @@ The home page SHALL render, in order: header/navigation, hero, manifesto, featur
|
|||||||
### Requirement: Listing and detail pages exist for catalog content
|
### Requirement: Listing and detail pages exist for catalog content
|
||||||
The system SHALL render a services listing (WEB-02) and a portfolio listing plus case detail (WEB-03) using the Heritage Editorial visual language. The case detail MUST present summary, event type, optional city/venue/date, challenge, solution, optional result, cover image and the ordered gallery. Portfolio listings and galleries MUST use alternating editorial image proportions on desktop while retaining DOM order and a single-column readable sequence on mobile.
|
The system SHALL render a services listing (WEB-02) and a portfolio listing plus case detail (WEB-03) using the Heritage Editorial visual language. The case detail MUST present summary, event type, optional city/venue/date, challenge, solution, optional result, cover image and the ordered gallery. Portfolio listings and galleries MUST use alternating editorial image proportions on desktop while retaining DOM order and a single-column readable sequence on mobile.
|
||||||
|
|
||||||
#### Scenario: Services listing shows published services
|
#### Scenario: Services listing renders editorial sections with published modalities
|
||||||
|
|
||||||
- **WHEN** a visitor loads `/servicos`
|
- **WHEN** a visitor loads `/servicos`
|
||||||
- **THEN** every published service MUST be listed with title and summary in `sort_order`
|
- **THEN** the page MUST present the two vertentes (Amare Casamentos and Amare Corporate) with CTAs to their sections
|
||||||
|
- **AND** every published wedding modality MUST be rendered in `sort_order` with tag, name, subtitle, summary and scope
|
||||||
|
- **AND** a quick-read comparison of the modalities MUST use each modality's `compare_heading` and `compare_summary`
|
||||||
|
- **AND** unpublished modalities MUST NOT be rendered
|
||||||
- **AND** the listing MUST use the public editorial layout (not an unrelated visual system)
|
- **AND** the listing MUST use the public editorial layout (not an unrelated visual system)
|
||||||
|
|
||||||
#### Scenario: Gallery respects stored order
|
#### Scenario: Gallery respects stored order
|
||||||
|
|||||||
@@ -42,8 +42,8 @@ class MediaPerformanceTest extends TestCase
|
|||||||
$about = $this->get(route('about'))->assertOk()->getContent();
|
$about = $this->get(route('about'))->assertOk()->getContent();
|
||||||
$detail = $this->get(route('portfolio.show', $firstCase->slug))->assertOk()->getContent();
|
$detail = $this->get(route('portfolio.show', $firstCase->slug))->assertOk()->getContent();
|
||||||
|
|
||||||
$this->assertMatchesRegularExpression('/service-first\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $services);
|
$this->assertStringNotContainsString('service-first.jpg', $services);
|
||||||
$this->assertMatchesRegularExpression('/service-later\.jpg"[^>]*loading="lazy"(?![^>]*fetchpriority)/', $services);
|
$this->assertStringNotContainsString('service-later.jpg', $services);
|
||||||
$this->assertMatchesRegularExpression('/case-first\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $portfolio);
|
$this->assertMatchesRegularExpression('/case-first\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $portfolio);
|
||||||
$this->assertMatchesRegularExpression('/case-later\.jpg"[^>]*loading="lazy"(?![^>]*fetchpriority)/', $portfolio);
|
$this->assertMatchesRegularExpression('/case-later\.jpg"[^>]*loading="lazy"(?![^>]*fetchpriority)/', $portfolio);
|
||||||
$this->assertMatchesRegularExpression('/about\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $about);
|
$this->assertMatchesRegularExpression('/about\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $about);
|
||||||
@@ -89,7 +89,7 @@ class MediaPerformanceTest extends TestCase
|
|||||||
$services = $this->get(route('services.index'))->assertOk()->getContent();
|
$services = $this->get(route('services.index'))->assertOk()->getContent();
|
||||||
$portfolio = $this->get(route('portfolio.index'))->assertOk()->getContent();
|
$portfolio = $this->get(route('portfolio.index'))->assertOk()->getContent();
|
||||||
|
|
||||||
$this->assertMatchesRegularExpression('/visible-service\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $services);
|
$this->assertStringNotContainsString('visible-service.jpg', $services);
|
||||||
$this->assertMatchesRegularExpression('/visible-case\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $portfolio);
|
$this->assertMatchesRegularExpression('/visible-case\.jpg"[^>]*loading="eager"[^>]*fetchpriority="high"/', $portfolio);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ namespace Tests\Feature\PublicSite;
|
|||||||
|
|
||||||
use App\Models\PortfolioCase;
|
use App\Models\PortfolioCase;
|
||||||
use App\Models\PortfolioImage;
|
use App\Models\PortfolioImage;
|
||||||
use App\Models\Service;
|
|
||||||
use App\Models\SiteSetting;
|
use App\Models\SiteSetting;
|
||||||
|
use App\Models\WeddingPackage;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Illuminate\Support\Facades\Cache;
|
use Illuminate\Support\Facades\Cache;
|
||||||
use Illuminate\Support\Facades\DB;
|
use Illuminate\Support\Facades\DB;
|
||||||
@@ -18,17 +18,45 @@ class PublicPagesTest extends TestCase
|
|||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase;
|
||||||
|
|
||||||
public function test_services_index_lists_published_services_in_sort_order(): void
|
public function test_services_index_renders_editorial_sections_with_published_modalities_only(): void
|
||||||
{
|
{
|
||||||
SiteSetting::instance();
|
SiteSetting::instance();
|
||||||
|
|
||||||
Service::factory()->create(['title' => 'Rascunho', 'published_at' => null]);
|
WeddingPackage::factory()->create(['name' => 'Rascunho', 'published_at' => null]);
|
||||||
Service::factory()->published()->create(['title' => 'Serviço B', 'sort_order' => 20]);
|
WeddingPackage::factory()->published()->create([
|
||||||
Service::factory()->published()->create(['title' => 'Serviço A', 'sort_order' => 10]);
|
'name' => 'Essenza',
|
||||||
|
'level' => '01 / COMPLETA',
|
||||||
|
'tag' => 'Assessoria completa',
|
||||||
|
'subtitle' => 'Do planejamento ao grande dia.',
|
||||||
|
'summary' => 'Para casais que desejam contar com a Amare desde o início.',
|
||||||
|
'scope_items' => ['Estruturação do planejamento', 'Coordenação da execução'],
|
||||||
|
'cta_label' => 'Quero conhecer a Essenza',
|
||||||
|
'compare_heading' => 'Começar com a Amare',
|
||||||
|
'compare_summary' => 'Acompanhamento mais amplo ao longo do planejamento.',
|
||||||
|
'sort_order' => 10,
|
||||||
|
]);
|
||||||
|
|
||||||
$this->get(route('services.index'))
|
$this->get(route('services.index'))
|
||||||
->assertOk()
|
->assertOk()
|
||||||
->assertSeeInOrder(['Serviço A', 'Serviço B'])
|
->assertSee('O cuidado certo para cada tipo de evento.')
|
||||||
|
->assertSee('Conhecer os serviços')
|
||||||
|
->assertSee('Tenho um evento em mente')
|
||||||
|
->assertSee('Duas vertentes')
|
||||||
|
->assertSee('Escolha por contexto, não por uma lista de pacotes.')
|
||||||
|
->assertSee('Amare Casamentos')
|
||||||
|
->assertSee('Acompanhamento para diferentes momentos do planejamento.')
|
||||||
|
->assertSee('Amare Corporate')
|
||||||
|
->assertSee('Planejamento e execução para eventos empresariais.')
|
||||||
|
->assertSee('Três formas de ter a Amare ao lado.')
|
||||||
|
->assertSee('Assessoria completa')
|
||||||
|
->assertSee('Essenza')
|
||||||
|
->assertSee('Do planejamento ao grande dia.')
|
||||||
|
->assertSee('Quero conhecer a Essenza')
|
||||||
|
->assertSee('Começar com a Amare')
|
||||||
|
->assertSee('Organização, produção e condução com linguagem empresarial.')
|
||||||
|
->assertSee('Estruturação do evento, escopo, prioridades e cronograma.')
|
||||||
|
->assertSee('Falar sobre um evento Corporate')
|
||||||
|
->assertSee('Do casamento ao evento corporativo, tudo começa com uma boa conversa.')
|
||||||
->assertDontSee('Rascunho');
|
->assertDontSee('Rascunho');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user