Files
amare/tests/Browser/MotionTest.php
manoel freitas b54908541f feat: add Dossiê vivo motion to the public site
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>
2026-08-05 19:40:40 -03:00

122 lines
3.9 KiB
PHP

<?php
declare(strict_types=1);
use App\Models\Service;
use App\Models\SiteSetting;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
beforeEach(function (): void {
SiteSetting::instance()->update([
'hero_title' => 'Celebrações com propósito',
'default_og_image_path' => 'media/hero.jpg',
'default_og_image_alt' => 'Capa editorial',
]);
Service::factory()->published()->featured()->create([
'title' => 'Casamentos',
'summary' => 'Assessoria completa',
]);
});
it('keeps home motion in final visible state when reduced motion is preferred', function (): void {
$page = $this->visit('/', [
'reducedMotion' => 'reduce',
]);
$state = $page->script(<<<'JS'
() => {
const hero = document.querySelector('[data-motion="dossie-hero"]');
const title = document.querySelector('#hero-heading');
const index = document.querySelector('[data-chapter-index]');
const active = document.querySelector('[data-chapter-index] [aria-current="true"]');
const titleStyle = title ? getComputedStyle(title) : null;
return {
heroActive: hero?.classList.contains('is-active') ?? false,
titleOpacity: titleStyle ? Number.parseFloat(titleStyle.opacity) : 0,
hasIndex: Boolean(index),
hasActiveChapter: Boolean(active),
};
}
JS);
expect($state['heroActive'])->toBeTrue();
expect($state['titleOpacity'])->toBeGreaterThan(0.9);
expect($state['hasIndex'])->toBeTrue();
expect($state['hasActiveChapter'])->toBeTrue();
});
it('activates the home focal opening once when motion is allowed', function (): void {
$page = $this->visit('/', [
'reducedMotion' => 'no-preference',
]);
$page->script(<<<'JS'
() => new Promise((resolve) => {
const wait = () => {
const hero = document.querySelector('[data-motion="dossie-hero"]');
if (hero?.classList.contains('is-active')) {
resolve(true);
return;
}
requestAnimationFrame(wait);
};
wait();
setTimeout(() => resolve(false), 2000);
})
JS);
$active = $page->script(<<<'JS'
() => document.querySelector('[data-motion="dossie-hero"]')?.classList.contains('is-active') ?? false
JS);
expect($active)->toBeTrue();
});
it('updates the active chapter while scrolling the home dossier', function (): void {
$page = $this->visit('/', [
'reducedMotion' => 'no-preference',
]);
$page->resize(1440, 1000);
$before = $page->script(<<<'JS'
() => document.querySelector('[data-chapter-index] [aria-current="true"]')?.getAttribute('href') ?? null
JS);
$page->script(<<<'JS'
() => {
const target = document.querySelector('#method-heading');
target?.scrollIntoView({ block: 'start' });
window.dispatchEvent(new Event('scroll'));
return Boolean(target);
}
JS);
$page->script(<<<'JS'
() => new Promise((resolve) => {
let frames = 0;
const check = () => {
const href = document.querySelector('[data-chapter-index] [aria-current="true"]')?.getAttribute('href');
if (href === '#method-heading' || frames > 60) {
resolve(href);
return;
}
frames += 1;
requestAnimationFrame(check);
};
check();
})
JS);
$after = $page->script(<<<'JS'
() => document.querySelector('[data-chapter-index] [aria-current="true"]')?.getAttribute('href') ?? null
JS);
expect($before)->not->toBeNull();
expect($after)->toBe('#method-heading');
});