Files
Aletheia/scripts/test-accessibility-layout.ps1
2026-07-16 18:46:28 +03:00

112 lines
3.9 KiB
PowerShell

$ErrorActionPreference = "Stop"
$repoRoot = Resolve-Path (Join-Path $PSScriptRoot "..")
$layoutRoot = Join-Path $repoRoot "app/src/main/res/layout"
$valuesRoot = Join-Path $repoRoot "app/src/main/res/values"
$themesPath = Join-Path $valuesRoot "themes.xml"
$failures = New-Object System.Collections.Generic.List[string]
function Add-Failure([string] $message) {
$failures.Add($message) | Out-Null
}
function Get-XmlLine([string] $content, [int] $index) {
if ($index -lt 0) {
return 1
}
return (($content.Substring(0, $index) -split "`n").Count)
}
function Get-AttributeValue([string] $block, [string] $attributeName) {
$escapedName = [regex]::Escape($attributeName)
$match = [regex]::Match($block, "$escapedName=""([^""]+)""")
if ($match.Success) {
return $match.Groups[1].Value
}
return $null
}
function Assert-MinDp([string] $value, [int] $minimum, [string] $where, [string] $attributeName) {
if ([string]::IsNullOrWhiteSpace($value)) {
Add-Failure "$where is missing $attributeName"
return
}
if ($value -notmatch "^([0-9]+)dp$") {
Add-Failure "$where has non-fixed $attributeName='$value'"
return
}
$actual = [int] $Matches[1]
if ($actual -lt $minimum) {
Add-Failure "$where has $attributeName=${actual}dp, expected at least ${minimum}dp"
}
}
$xmlFiles = Get-ChildItem -Path @($layoutRoot, $valuesRoot) -Filter "*.xml" -Recurse
foreach ($file in $xmlFiles) {
$content = Get-Content $file.FullName -Raw -Encoding UTF8
$relativePath = Resolve-Path -Relative $file.FullName
$textSizeDpMatches = [regex]::Matches($content, 'android:textSize="[0-9.]+dp"')
foreach ($match in $textSizeDpMatches) {
$line = Get-XmlLine $content $match.Index
Add-Failure "${relativePath}:$line uses dp for textSize; use sp"
}
$materialButtons = [regex]::Matches($content, '(?s)<com\.google\.android\.material\.button\.MaterialButton\b.*?/>')
foreach ($match in $materialButtons) {
$line = Get-XmlLine $content $match.Index
$where = "${relativePath}:$line MaterialButton"
$block = $match.Value
if ($block -match 'android:minWidth="0dp"') {
Add-Failure "$where resets minWidth to 0dp"
}
$minHeight = Get-AttributeValue $block "android:minHeight"
if (-not [string]::IsNullOrWhiteSpace($minHeight)) {
Assert-MinDp $minHeight 48 $where "android:minHeight"
}
}
$imageButtons = [regex]::Matches($content, '(?s)<ImageButton\b.*?/>')
foreach ($match in $imageButtons) {
$line = Get-XmlLine $content $match.Index
$where = "${relativePath}:$line ImageButton"
$block = $match.Value
Assert-MinDp (Get-AttributeValue $block "android:layout_width") 48 $where "android:layout_width"
Assert-MinDp (Get-AttributeValue $block "android:layout_height") 48 $where "android:layout_height"
}
}
$themesContent = Get-Content $themesPath -Raw -Encoding UTF8
foreach ($styleName in @("Primary", "Secondary", "Tonal")) {
$stylePattern = "(?s)<style\s+name=""Widget\.Aletheia\.Button\.$styleName"".*?</style>"
$styleMatch = [regex]::Match($themesContent, $stylePattern)
if (-not $styleMatch.Success) {
Add-Failure "themes.xml is missing Widget.Aletheia.Button.$styleName"
continue
}
$heightMatch = [regex]::Match($styleMatch.Value, '<item\s+name="android:minHeight">([0-9]+)dp</item>')
if (-not $heightMatch.Success) {
Add-Failure "Widget.Aletheia.Button.$styleName is missing android:minHeight"
continue
}
$height = [int] $heightMatch.Groups[1].Value
if ($height -lt 48) {
Add-Failure "Widget.Aletheia.Button.$styleName has android:minHeight=${height}dp, expected at least 48dp"
}
}
if ($failures.Count -gt 0) {
Write-Error ("Accessibility layout smoke test failed:`n" + ($failures -join "`n"))
}
Write-Host "Accessibility layout smoke test passed."