Files
amare/tests/Browser/HomeEditorialCadenceTest.php

157 lines
6.2 KiB
PHP

<?php
declare(strict_types=1);
use Database\Seeders\VisualContentSeeder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Artisan;
uses(RefreshDatabase::class);
beforeEach(function (): void {
Artisan::call('db:seed', ['--class' => VisualContentSeeder::class, '--force' => true]);
});
it('keeps the hero asymmetric on desktop and stacked through md and mobile', function (): void {
$page = $this->visit('/', [
'reducedMotion' => 'reduce',
]);
$waitFrames = '() => new Promise((resolve) => requestAnimationFrame(() => requestAnimationFrame(resolve)))';
$page->resize(1440, 1000);
$page->script($waitFrames);
$desktop = $page->script(<<<'JS'
() => {
const header = document.querySelector('.site-header');
const hero = document.querySelector('[data-chapter="hero"]');
const content = hero?.querySelector('[data-hero-content]');
const media = hero?.querySelector('[data-split-hero]');
const headerRect = header?.getBoundingClientRect();
const heroRect = hero?.getBoundingClientRect();
const contentRect = content?.getBoundingClientRect();
const mediaRect = media?.getBoundingClientRect();
return {
hasContentColumn: Boolean(content),
startsBelowHeader: Math.abs((heroRect?.top ?? -1) - (headerRect?.bottom ?? -2)) <= 1,
mediaBesideContent: (mediaRect?.left ?? 0) >= (contentRect?.right ?? Number.POSITIVE_INFINITY) - 1,
mediaMinHeight: Math.round(mediaRect?.height ?? 0) >= 519,
mediaTouchesViewportRight: (mediaRect?.right ?? 0) >= window.innerWidth - 4,
horizontalOverflow: document.documentElement.scrollWidth > window.innerWidth,
};
}
JS);
expect($desktop)->toBe([
'hasContentColumn' => true,
'startsBelowHeader' => true,
'mediaBesideContent' => true,
'mediaMinHeight' => true,
'mediaTouchesViewportRight' => true,
'horizontalOverflow' => false,
]);
$page->resize(767, 1000);
$page->script($waitFrames);
$md = $page->script(<<<'JS'
() => {
const hero = document.querySelector('[data-chapter="hero"]');
const content = hero?.querySelector('[data-hero-content]');
const media = hero?.querySelector('[data-split-hero]');
const contentRect = content?.getBoundingClientRect();
const mediaRect = media?.getBoundingClientRect();
return {
hasContentColumn: Boolean(content),
mediaFollowsContent: (mediaRect?.top ?? 0) >= (contentRect?.bottom ?? Number.POSITIVE_INFINITY) - 1,
mediaFillsContainerWidth: (mediaRect?.width ?? 0) > window.innerWidth - 100,
mediaMinHeight: Math.round(mediaRect?.height ?? 0) >= 319,
horizontalOverflow: document.documentElement.scrollWidth > window.innerWidth,
};
}
JS);
expect($md)->toBe([
'hasContentColumn' => true,
'mediaFollowsContent' => true,
'mediaFillsContainerWidth' => true,
'mediaMinHeight' => true,
'horizontalOverflow' => false,
]);
$page->resize(390, 844);
$page->script($waitFrames);
$mobile = $page->script(<<<'JS'
() => {
const hero = document.querySelector('[data-chapter="hero"]');
const content = hero?.querySelector('[data-hero-content]');
const media = hero?.querySelector('[data-split-hero]');
const contentRect = content?.getBoundingClientRect();
const mediaRect = media?.getBoundingClientRect();
return {
hasContentColumn: Boolean(content),
mediaFollowsContent: (mediaRect?.top ?? 0) >= (contentRect?.bottom ?? Number.POSITIVE_INFINITY) - 1,
mediaFillsContainerWidth: (mediaRect?.width ?? 0) > window.innerWidth - 100,
horizontalOverflow: document.documentElement.scrollWidth > window.innerWidth,
};
}
JS);
expect($mobile)->toBe([
'hasContentColumn' => true,
'mediaFollowsContent' => true,
'mediaFillsContainerWidth' => true,
'horizontalOverflow' => false,
]);
});
it('keeps the full home cadence accessible and contained at both viewports', function (): void {
$page = $this->visit('/', [
'reducedMotion' => 'reduce',
]);
foreach ([[1440, 1000], [390, 844]] as [$width, $height]) {
$page->resize($width, $height);
$page->assertNoAccessibilityIssues(1);
$layout = $page->script(<<<'JS'
() => {
const chapters = Array.from(document.querySelectorAll('.home-chapter'));
const clippedValues = new Set(['clip', 'hidden']);
const textNodes = Array.from(document.querySelectorAll(
'.home-chapters h1, .home-chapters h2, .home-chapters h3, .home-chapters p, .home-chapters a, .home-chapters span'
));
return {
horizontalOverflow: document.documentElement.scrollWidth > window.innerWidth,
overlappingChapters: chapters.slice(1).some((chapter, index) => {
const previous = chapters[index].getBoundingClientRect();
const current = chapter.getBoundingClientRect();
return current.top < previous.bottom - 1;
}),
ornamentalFolios: document.querySelectorAll('[data-home-folio]').length,
clippedText: textNodes.filter((node) => {
const style = getComputedStyle(node);
const clippedX = clippedValues.has(style.overflowX) && node.scrollWidth > node.clientWidth + 1;
const clippedY = clippedValues.has(style.overflowY) && node.scrollHeight > node.clientHeight + 1;
return clippedX || clippedY;
}).length,
};
}
JS);
expect($layout)->toBe([
'horizontalOverflow' => false,
'overlappingChapters' => false,
'ornamentalFolios' => 0,
'clippedText' => 0,
]);
}
});