test: enforce accessible portfolio interaction
This commit is contained in:
210
docs/accessibility/screen-reader-scripts.md
Normal file
210
docs/accessibility/screen-reader-scripts.md
Normal file
@@ -0,0 +1,210 @@
|
||||
# Physical screen-reader test scripts
|
||||
|
||||
Run these scripts against the exact release candidate. Do not simulate a
|
||||
screen reader with the accessibility tree, and do not mark a row complete from
|
||||
automated output. Record the operating-system, browser, and screen-reader
|
||||
versions plus the commit/build identifier in the WCAG checklist.
|
||||
|
||||
## Test states
|
||||
|
||||
Use a fresh private window/profile for each state unless the step explicitly
|
||||
requires saved preference state.
|
||||
|
||||
1. **Default** — normal motion preference, sound not started.
|
||||
2. **Audio running** — activate **START THE DRIVE** once.
|
||||
3. **Static** — choose **Static** from **Quality**.
|
||||
4. **Reduced motion** — enable the OS reduced-motion preference before load.
|
||||
5. **Media/scene failure** — use the release test build's documented failure
|
||||
setup; never alter production code or expose a public test hook.
|
||||
6. **Missing social** — use the approved optional-social build fixture; the
|
||||
email action must remain.
|
||||
|
||||
For each platform, repeat Tasks 1–3 and Task 7 in all six states. Run Tasks
|
||||
4–6 in every state where their content is present. If final project media is
|
||||
still awaiting approval, record Tasks 5–6 as **not present in candidate — must
|
||||
re-run when approved media enters the manifest**, not as PASS.
|
||||
|
||||
## NVDA + Firefox on Windows
|
||||
|
||||
Setup:
|
||||
|
||||
- Start NVDA, then Firefox. Record exact versions from NVDA Help → About and
|
||||
Firefox Help → About.
|
||||
- Use a fresh Firefox private window at 100% zoom for the default pass.
|
||||
- Keep NVDA speech viewer open only if it does not change viewport geometry.
|
||||
- Use `NVDA+F7` for the Elements List, `H`/`Shift+H` for headings,
|
||||
`D`/`Shift+D` for landmarks, `K`/`Shift+K` for links, `B` for buttons,
|
||||
`F` for form fields, `Tab`/`Shift+Tab` for focus order, and `Enter`/`Space`
|
||||
for activation.
|
||||
|
||||
Run the seven literal tasks below. Record the exact announcement when an
|
||||
oracle fails; do not paraphrase the failure.
|
||||
|
||||
## VoiceOver + Safari on macOS
|
||||
|
||||
Setup:
|
||||
|
||||
- Record macOS and Safari versions, enable VoiceOver with `Command+F5`, and
|
||||
record the VoiceOver version from VoiceOver Utility → About.
|
||||
- Enable Safari's **Press Tab to highlight each item on a webpage**.
|
||||
- Use `VO` (`Control+Option`) + `U` for the rotor, `VO+Command+H` for the next
|
||||
heading, `VO+Command+L` for the next link, `VO+Command+J` for the next form
|
||||
control, `VO+Right/Left Arrow` for sequential reading, and `VO+Space` to
|
||||
activate.
|
||||
|
||||
Run the seven literal tasks below in Safari. Note whether Quick Nav is on for
|
||||
each run because it changes key behavior, not page semantics.
|
||||
|
||||
## VoiceOver + Safari on iOS
|
||||
|
||||
Setup:
|
||||
|
||||
- Record device model, iOS version, and Safari build. Enable VoiceOver in
|
||||
Settings → Accessibility → VoiceOver.
|
||||
- Set the rotor to Headings, Links, Form Controls, and Containers as needed.
|
||||
- Use one-finger right/left swipes for sequential navigation, rotor swipes for
|
||||
category navigation, double-tap to activate, and a four-finger tap near the
|
||||
top/bottom to move to the first/last accessible item.
|
||||
- Test portrait at the 320 CSS px-equivalent supported width and landscape.
|
||||
|
||||
Run the same seven tasks. Also confirm that touch exploration never lands on
|
||||
the decorative canvas, road signs, speed, particles, or HUD.
|
||||
|
||||
## Seven literal tasks and pass oracles
|
||||
|
||||
### 1. Load, identity, structure, and scene description
|
||||
|
||||
1. Load the page at the top without interacting.
|
||||
2. Read from the first accessible item through the main navigation.
|
||||
3. Open the landmarks/headings rotor or Elements List.
|
||||
|
||||
Pass only when:
|
||||
|
||||
- the document title identifies Luca Pîslaru and the portfolio role;
|
||||
- **Skip to portfolio content** is the first actionable item;
|
||||
- exactly one H1 announces **Luca Pîslaru**, followed by **System
|
||||
Administrator & Full-Stack Developer**;
|
||||
- the portfolio navigation has a useful name and ordered section links;
|
||||
- one concise description explains the restrained retro-futuristic road
|
||||
journey and portfolio progress;
|
||||
- the canvas, poster, car, road signs, speed, particles, and HUD do not appear
|
||||
as separate accessible objects or repeated live announcements.
|
||||
|
||||
### 2. Skip link, section navigation, focus, and passive scrolling
|
||||
|
||||
1. Return to the top and focus **Skip to portfolio content** with the keyboard
|
||||
or rotor.
|
||||
2. Activate it and read the focused item.
|
||||
3. Navigate back to the section navigation, activate **Infrastructure**, and
|
||||
read the focused item.
|
||||
4. Move through **Selected Builds**, **Toolkit**, and **Contact** using only
|
||||
the navigation links.
|
||||
5. Put the reading cursor on a navigation link, then scroll manually without
|
||||
activating it. Use Back/Forward once after an explicit section activation.
|
||||
|
||||
Pass only when:
|
||||
|
||||
- skip activation lands on the portfolio main content;
|
||||
- explicit section navigation focuses and announces the correct H2 once;
|
||||
- logical focus order matches the visible document order;
|
||||
- focus is visible and not covered by the fixed HUD or drive controls;
|
||||
- passive scrolling and history restoration do not steal keyboard focus or
|
||||
relocate the screen-reader reading cursor.
|
||||
|
||||
### 3. Start the Drive and audio controls
|
||||
|
||||
1. Find **START THE DRIVE** by button navigation.
|
||||
2. Read the button and its adjacent supporting description before activating.
|
||||
3. Activate it once, then navigate through the newly exposed sound controls.
|
||||
4. Activate **Mute sound**, verify the name becomes **Unmute sound**, adjust
|
||||
**Sound volume**, and mute again before continuing.
|
||||
|
||||
Pass only when:
|
||||
|
||||
- the control is announced as a button and the nearby text explains that it
|
||||
enables the interactive soundtrack;
|
||||
- sound never begins before explicit activation;
|
||||
- **Mute sound**/**Unmute sound** and **Sound volume** have correct role,
|
||||
name, and current value/state;
|
||||
- audio state changes are understandable without repeated or continuous live
|
||||
announcements and do not drown out assistive-technology speech;
|
||||
- audio failure, when tested, announces **Audio unavailable** while all
|
||||
portfolio content remains usable.
|
||||
|
||||
### 4. Toolkit labels
|
||||
|
||||
1. Navigate to **Toolkit** and enter each technology group.
|
||||
2. Read at least Linux, Docker, Python, Vue.js, C# / .NET, and the Additional
|
||||
experience group in sequence.
|
||||
|
||||
Pass only when each technology is announced once from its visible text label;
|
||||
the decorative repeated icon/dot is silent; group headings are announced in
|
||||
the expected hierarchy; and no percentage, rating, or invented expertise
|
||||
claim is exposed.
|
||||
|
||||
### 5. Chart descriptions and data tables
|
||||
|
||||
1. Navigate to the Opinion Dynamics Simulation chart group, if present in the
|
||||
approved candidate.
|
||||
2. Read the figure caption, adjacent Variables, Trend, and Conclusion fields.
|
||||
3. Enter any data table by table navigation and traverse its headers and at
|
||||
least two data cells.
|
||||
|
||||
Pass only when the purpose, axes/variables, trend, and conclusion are usable
|
||||
without inspecting color or pixels; each table has a useful caption and
|
||||
associated row/column headers; and the image alt does not redundantly recite
|
||||
the full adjacent description.
|
||||
|
||||
### 6. Authored video controls and failure fallback
|
||||
|
||||
1. Navigate to an approved project video, if present in the candidate.
|
||||
2. Read its name, caption, structured description, initial status, and authored
|
||||
**Play video** control.
|
||||
3. Activate Play, verify **Pause video**, pause, then repeat with OS reduced
|
||||
motion enabled.
|
||||
4. Run the approved media-failure state and revisit the same figure.
|
||||
|
||||
Pass only when no sound autoplays; reduced motion begins from a poster until
|
||||
explicit Play; the authored button exposes the correct play/pause state; the
|
||||
caption/description remains available; failure exposes **Video unavailable**
|
||||
and explanatory text; and inaccessible user-agent shadow controls are not the
|
||||
only control surface.
|
||||
|
||||
### 7. Contact and optional social links
|
||||
|
||||
1. Navigate to **Contact** by heading and by the section navigation.
|
||||
2. Read Luca's name, role, visible email address, CV/contact note, and every
|
||||
optional profile link.
|
||||
3. Inspect the email link's destination/purpose without sending mail.
|
||||
4. Repeat in the missing-social state.
|
||||
|
||||
Pass only when:
|
||||
|
||||
- the visible email and primary `mailto:` action are announced with an
|
||||
unambiguous purpose;
|
||||
- GitHub, GitLab, and LinkedIn have distinct visible/accessibility names when
|
||||
present;
|
||||
- missing optional social links are omitted rather than announced as empty,
|
||||
disabled, or placeholder controls;
|
||||
- the email action remains reachable and the page exposes no CV download.
|
||||
|
||||
## Result template
|
||||
|
||||
Copy one row per state/platform into the WCAG checklist evidence log:
|
||||
|
||||
```text
|
||||
Date/time:
|
||||
Build/commit:
|
||||
OS/device:
|
||||
Browser + version:
|
||||
Screen reader + version:
|
||||
State:
|
||||
Tasks run: 1 2 3 4 5 6 7
|
||||
Result: PASS / FAIL / NOT PRESENT — RE-RUN REQUIRED
|
||||
Exact failed announcement or interaction:
|
||||
Screenshot/speech-viewer/video evidence location (private):
|
||||
Tester:
|
||||
```
|
||||
|
||||
Never place private hostnames, private project names, credentials, personal
|
||||
account identifiers, or uncleared media in the committed evidence log.
|
||||
Reference in New Issue
Block a user