fix: address self-review findings
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Adversarial tests for lint-skin.py's accessible-SVG contract."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
ROOT = Path(__file__).resolve().parent.parent
|
||||
LINTER = ROOT / "scripts/lint-skin.py"
|
||||
|
||||
VALID_SVG = """\
|
||||
<svg xmlns="http://www.w3.org/2000/svg" role="img"
|
||||
aria-labelledby="fixture-title fixture-desc">
|
||||
<title id="fixture-title">Fixture diagram</title>
|
||||
<desc id="fixture-desc">Diagram showing a fixture connected to a result.</desc>
|
||||
<rect width="10" height="10"/>
|
||||
</svg>
|
||||
"""
|
||||
|
||||
|
||||
def run_linter(path: Path) -> subprocess.CompletedProcess[str]:
|
||||
return subprocess.run(
|
||||
[sys.executable, str(LINTER), str(path)],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
check=False,
|
||||
)
|
||||
|
||||
|
||||
def require_failure(name: str, html: str, expected: str, directory: Path) -> None:
|
||||
path = directory / f"{name}.html"
|
||||
path.write_text(html, encoding="utf-8")
|
||||
result = run_linter(path)
|
||||
if result.returncode != 1:
|
||||
raise AssertionError(
|
||||
f"{name}: expected exit 1, got {result.returncode}\n{result.stdout}{result.stderr}"
|
||||
)
|
||||
if f"a11y: {expected}" not in result.stdout:
|
||||
raise AssertionError(
|
||||
f"{name}: missing expected a11y finding {expected!r}\n{result.stdout}"
|
||||
)
|
||||
print(f"OK: {name} rejected — {expected}")
|
||||
|
||||
|
||||
def require_pass(name: str, html: str, directory: Path) -> None:
|
||||
path = directory / f"{name}.html"
|
||||
path.write_text(html, encoding="utf-8")
|
||||
result = run_linter(path)
|
||||
if result.returncode != 0:
|
||||
raise AssertionError(
|
||||
f"{name}: expected exit 0, got {result.returncode}\n{result.stdout}{result.stderr}"
|
||||
)
|
||||
if "a11y:" in result.stdout:
|
||||
raise AssertionError(f"{name}: unexpected a11y finding\n{result.stdout}")
|
||||
print(f"OK: {name} accepted")
|
||||
|
||||
|
||||
def main() -> int:
|
||||
with tempfile.TemporaryDirectory(prefix="lint-a11y-") as temp_dir:
|
||||
directory = Path(temp_dir)
|
||||
|
||||
require_failure(
|
||||
"missing-role",
|
||||
VALID_SVG.replace(' role="img"', ""),
|
||||
'diagram <svg> must carry role="img"',
|
||||
directory,
|
||||
)
|
||||
require_failure(
|
||||
"unresolved-labelled-by",
|
||||
VALID_SVG.replace(
|
||||
'aria-labelledby="fixture-title fixture-desc"',
|
||||
'aria-labelledby="absent-title absent-desc"',
|
||||
),
|
||||
"aria-labelledby references missing id(s): absent-title, absent-desc",
|
||||
directory,
|
||||
)
|
||||
require_failure(
|
||||
"labels-unrelated-elements",
|
||||
VALID_SVG.replace(' id="fixture-title"', "")
|
||||
.replace(' id="fixture-desc"', "")
|
||||
.replace(
|
||||
' <rect width="10" height="10"/>',
|
||||
' <g id="fixture-title"></g>\n'
|
||||
' <g id="fixture-desc"></g>\n'
|
||||
' <rect width="10" height="10"/>',
|
||||
),
|
||||
"aria-labelledby must name the <title> and <desc> IDs",
|
||||
directory,
|
||||
)
|
||||
require_failure(
|
||||
"late-title",
|
||||
VALID_SVG.replace(
|
||||
' <title id="fixture-title">Fixture diagram</title>\n <desc',
|
||||
' <defs></defs>\n <title id="fixture-title">Fixture diagram</title>\n <desc',
|
||||
),
|
||||
"<title> must be the first child element of <svg>",
|
||||
directory,
|
||||
)
|
||||
require_failure(
|
||||
"empty-desc",
|
||||
VALID_SVG.replace(
|
||||
"Diagram showing a fixture connected to a result.", " "
|
||||
),
|
||||
"<desc> must not be empty",
|
||||
directory,
|
||||
)
|
||||
require_failure(
|
||||
"bare-ids",
|
||||
VALID_SVG.replace("fixture-title", "title").replace(
|
||||
"fixture-desc", "desc"
|
||||
),
|
||||
'bare id="title" and id="desc" are not allowed',
|
||||
directory,
|
||||
)
|
||||
require_pass(
|
||||
"decorative",
|
||||
'<svg xmlns="http://www.w3.org/2000/svg" aria-hidden="true">'
|
||||
'<path d="M0 0h1v1z"/></svg>\n',
|
||||
directory,
|
||||
)
|
||||
|
||||
print("All accessible-SVG lint cases passed.")
|
||||
return 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main())
|
||||
Reference in New Issue
Block a user