Introduce a focal Home opening, chapter index, and restrained continuity reveals while keeping reduced-motion and visual baselines intact. Co-authored-by: Cursor <cursoragent@cursor.com>
131 lines
3.7 KiB
PHP
131 lines
3.7 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Models\PortfolioCase;
|
|
use App\Models\SiteSetting;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(function (): void {
|
|
SiteSetting::instance();
|
|
});
|
|
|
|
it('has no critical or serious accessibility issues on covered public routes', function (): void {
|
|
$case = PortfolioCase::factory()->published()->create([
|
|
'slug' => 'casamento-jardim',
|
|
'title' => 'Casamento Jardim',
|
|
]);
|
|
|
|
$routes = [
|
|
'/',
|
|
'/servicos',
|
|
'/portfolio',
|
|
'/portfolio/'.$case->slug,
|
|
];
|
|
|
|
foreach ($routes as $route) {
|
|
$this->visit($route)
|
|
->assertNoAccessibilityIssues(1);
|
|
}
|
|
});
|
|
|
|
it('exposes brand mark and operable mobile menu toggle', function (): void {
|
|
$page = $this->visit('/');
|
|
|
|
$brandAlt = $page->script('() => document.querySelector("img.brand-logo")?.getAttribute("alt")');
|
|
expect(strtolower((string) $brandAlt))->toContain('amare');
|
|
|
|
$page->resize(390, 844);
|
|
|
|
$expandedBefore = $page->script('() => document.querySelector("[data-menu-button]")?.getAttribute("aria-expanded")');
|
|
expect($expandedBefore)->toBe('false');
|
|
|
|
$page->click('[data-menu-button]');
|
|
|
|
$expandedAfter = $page->script('() => document.querySelector("[data-menu-button]")?.getAttribute("aria-expanded")');
|
|
expect($expandedAfter)->toBe('true');
|
|
|
|
$navVisible = $page->script('() => {
|
|
const nav = document.querySelector("[data-main-nav]");
|
|
if (!nav) return false;
|
|
const style = getComputedStyle(nav);
|
|
return style.display !== "none" && style.visibility !== "hidden";
|
|
}');
|
|
expect($navVisible)->toBeTrue();
|
|
});
|
|
|
|
it('reaches the primary CTA by keyboard and activates it', function (): void {
|
|
$page = $this->visit('/');
|
|
|
|
$page->script('() => document.querySelector(\'a[href="#conteudo"]\')?.focus()');
|
|
|
|
$reachedCta = false;
|
|
|
|
for ($i = 0; $i < 30; $i++) {
|
|
$testId = $page->script('() => document.activeElement?.getAttribute("data-testid")');
|
|
|
|
if ($testId === 'home-primary-cta') {
|
|
$reachedCta = true;
|
|
break;
|
|
}
|
|
|
|
$page->keys(':focus', 'Tab');
|
|
}
|
|
|
|
expect($reachedCta)->toBeTrue();
|
|
|
|
$outlineStyle = $page->script('() => getComputedStyle(document.activeElement).outlineStyle');
|
|
expect($outlineStyle)->not->toBe('none');
|
|
|
|
$page->keys('[data-testid="home-primary-cta"]', 'Enter')
|
|
->assertPathIs('/contato');
|
|
});
|
|
|
|
it('loads covered public routes without console errors', function (): void {
|
|
$case = PortfolioCase::factory()->published()->create([
|
|
'slug' => 'casamento-jardim',
|
|
]);
|
|
|
|
foreach (['/', '/servicos', '/portfolio', '/portfolio/'.$case->slug] as $route) {
|
|
$this->visit($route)
|
|
->assertNoJavaScriptErrors();
|
|
}
|
|
});
|
|
|
|
it('disables transitions when prefers-reduced-motion is reduce', function (): void {
|
|
$case = PortfolioCase::factory()->published()->create([
|
|
'slug' => 'casamento-jardim',
|
|
]);
|
|
|
|
$routes = [
|
|
'/',
|
|
'/servicos',
|
|
'/portfolio',
|
|
'/portfolio/'.$case->slug,
|
|
'/sobre',
|
|
'/contato',
|
|
'/privacidade',
|
|
];
|
|
|
|
foreach ($routes as $route) {
|
|
$page = $this->visit($route, [
|
|
'reducedMotion' => 'reduce',
|
|
]);
|
|
|
|
$duration = $page->script(<<<'JS'
|
|
() => {
|
|
const probe = document.createElement('div');
|
|
probe.style.transition = 'opacity var(--amare-duration-normal) ease';
|
|
document.body.appendChild(probe);
|
|
const value = getComputedStyle(probe).transitionDuration;
|
|
probe.remove();
|
|
return value;
|
|
}
|
|
JS);
|
|
|
|
expect((float) $duration)->toBeLessThan(0.02);
|
|
}
|
|
});
|