feat(i18n): accessibility - per-field form errors, landmark aria-labels, tests (closes #76)
This commit is contained in:
119
tests/Views/LayoutA11yTest.php
Normal file
119
tests/Views/LayoutA11yTest.php
Normal file
@@ -0,0 +1,119 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Tests\Views;
|
||||
|
||||
use PHPUnit\Framework\Attributes\Test;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
/**
|
||||
* Static a11y checks for the shared layout
|
||||
* (`app/views/layouts/main.php`). We verify the layout's *source*
|
||||
* carries the right ARIA / landmark attributes rather than spinning
|
||||
* up the full render (which would need nav, OG, structured-data,
|
||||
* server-vars, and a dozen more locals). The home view is tested
|
||||
* for content-level a11y in `HomeViewA11yTest`.
|
||||
*/
|
||||
final class LayoutA11yTest extends TestCase
|
||||
{
|
||||
private string $layoutSource;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
$path = dirname(__DIR__, 2) . '/app/views/layouts/main.php';
|
||||
self::assertFileExists($path);
|
||||
$this->layoutSource = (string) file_get_contents($path);
|
||||
self::assertNotEmpty($this->layoutSource);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function htmlRootCarriesLangAttribute(): void
|
||||
{
|
||||
// The layout emits <html lang="..."> with the value rendered by PHP from
|
||||
// the $locale variable (not literally `$locale` between quotes).
|
||||
// We assert the source binds lang to the $locale variable inside PHP output.
|
||||
self::assertStringContainsString('<html lang="', $this->layoutSource);
|
||||
self::assertStringContainsString('$locale', $this->layoutSource);
|
||||
// Make sure $locale actually flows into the lang attribute (basic
|
||||
// co-occurrence check on the same <html ...> opening tag).
|
||||
self::assertMatchesRegularExpression(
|
||||
'~<html\b[^>]*\blang=[^>]*\$locale~s',
|
||||
$this->layoutSource,
|
||||
'Layout must bind <html lang> to the current locale'
|
||||
);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function skipLinkPointsAtMain(): void
|
||||
{
|
||||
self::assertStringContainsString('class="skip-link"', $this->layoutSource);
|
||||
self::assertStringContainsString('href="#main"', $this->layoutSource);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function mainLandmarkHasIdAndAriaLabel(): void
|
||||
{
|
||||
self::assertMatchesRegularExpression(
|
||||
'/<main\b[^>]*\bid="main"/',
|
||||
$this->layoutSource
|
||||
);
|
||||
self::assertMatchesRegularExpression(
|
||||
'/<main\b[^>]*\baria-label=/',
|
||||
$this->layoutSource
|
||||
);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function navLandmarkHasAriaLabel(): void
|
||||
{
|
||||
self::assertMatchesRegularExpression(
|
||||
'/<nav\b[^>]*\baria-label=/',
|
||||
$this->layoutSource
|
||||
);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function footerHasRoleAndLabel(): void
|
||||
{
|
||||
self::assertMatchesRegularExpression(
|
||||
'/<footer\b[^>]*\baria-label=/',
|
||||
$this->layoutSource
|
||||
);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function lightboxIsADialogModal(): void
|
||||
{
|
||||
self::assertStringContainsString('id="lightbox"', $this->layoutSource);
|
||||
self::assertStringContainsString('role="dialog"', $this->layoutSource);
|
||||
self::assertStringContainsString('aria-modal="true"', $this->layoutSource);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function lightboxImageCarriesAltAttribute(): void
|
||||
{
|
||||
self::assertMatchesRegularExpression(
|
||||
'/<img\b[^>]*\bid="lightboxImg"[^>]*\balt=/',
|
||||
$this->layoutSource
|
||||
);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function localeSwitcherHostIsAriaLabeled(): void
|
||||
{
|
||||
// The LocaleSwitcher widget uses aria-label on its <ul>.
|
||||
self::assertStringContainsString('aria-label="', $this->layoutSource);
|
||||
}
|
||||
|
||||
#[Test]
|
||||
public function mobileNavToggleIsKeyboardAccessible(): void
|
||||
{
|
||||
self::assertMatchesRegularExpression(
|
||||
'/<button\b[^>]*\bclass="nav-hamburger"/',
|
||||
$this->layoutSource
|
||||
);
|
||||
self::assertStringContainsString('aria-expanded=', $this->layoutSource);
|
||||
self::assertStringContainsString('aria-controls=', $this->layoutSource);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user