docs(audit): Q.DEFER.004 — Playwright+axe-core verification 2026-05-13

Verified 3 pages with axe-core 4.10 CDN-injected via Playwright MCP:
- /deals (sub-A): 6 label violations REMAIN — Vuetify 3.12 silently drops
  aria-label на v-checkbox-btn (Task 1 source fix не propagates через rendering)
- /admin/supplier-prices (sub-B): 9 label violations REMAIN — 6× v-text-field
  с orphan aria-labelledby + 3× v-switch без aria-label на native input
- /admin/tenants (sub-C): 1 aria-tooltip-name violation confirmed как
  Vuetify-internal artifact (documented limitation, button activator OK)

Root cause: общий Vuetify-internal a11y prop forwarding gap. Source-level
Task 1 + Task 2 fixes присутствуют в коммитах d9fc3d9/c8005e0, но не имеют
user-visible effect — те же 16 residual nodes что pre-fix. Library-level
limitation, не application defect.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-05-13 00:48:59 +03:00
parent 484504b78f
commit e79fe95267
@@ -186,6 +186,22 @@ C. Vuetify v-tooltip eager-mount artifact (aria-tooltip-name): role="tooltip" ov
**Sub-C status:** Vuetify v-tooltip создаёт `<div role="tooltip" id="v-tooltip-v-N">` pre-emptively (до показа), без content. axe-core reports aria-tooltip-name serious violation. **Application-level mitigation уже на месте:** activator button (TenantsTable.vue:89) имеет `:aria-label="Войти как клиент (impersonation) для ${item.name}"`. Workaround «убрать v-tooltip и использовать HTML title» — теряем Vuetify styling + теряем tooltip activator behavior; не оправдано ради cosmetic violation. **Upstream fix tracking:** оставить как known issue до Vuetify 3.13+ (если содержит fix), либо до polish-sprint post-MVP.
**Verification 2026-05-13 (Playwright + axe-core 4.10 CDN inject, dev mode):**
- **`/deals` (sub-A post-fix):** ❌ **6 `label` violations critical остаются** на `#input-v-41..48` — native `input[type=checkbox]` внутри `v-checkbox-btn` без атрибутов aria-label/aria-labelledby. Source code DealsTable.vue:127141 содержит `aria-label="Выбрать все сделки"` + `:aria-label="\`Выбрать сделку «${item.name}»\`"`, но Vuetify 3.12 **silently drops** aria-label на`v-checkbox-btn` — не forwarded ни на wrapper `div.v-selection-control`, ни на native input-элемент. То есть Task 1 fix присутствует в source, но не пробивается через Vuetify rendering layer. Root cause тот же класс, что у sub-C — Vuetify-internal a11y prop forwarding gap.
- **`/admin/supplier-prices` (sub-B post-fix):** ❌ **9 `label` violations critical остаются**: (a) 6× `v-text-field` (`#input-v-23/26/33/36/43/46`) имеют `aria-labelledby="input-v-XX-label"`, но referenced label-элемент **не существует в DOM** (Vuetify не рендерит label-target когда нет `label` prop, оставляя orphan reference); (b) 3× `v-switch` (`#switch-v-28/38/48`) — plain `input[type=checkbox]` без aria-label на native input. Source AdminSupplierPricesView.vue:737 содержит `:aria-label="\`Cost (₽) для ${item.name}\`"` + аналоги, но они не достигают native input-элемента.
- **`/admin/tenants` (sub-C):** ✅ Подтверждено как documented: 1 `aria-tooltip-name` violation serious на `div.v-overlay.v-tooltip#v-tooltip-v-59[role=tooltip]` — Vuetify-internal artifact, button activator имеет own `aria-label` (application-level a11y OK). 0 `label` violations на этой странице.
**Verdict:** все 3 sub-items имеют **общий root cause** — Vuetify 3.12 не пропускает custom aria-attributes на native input/tooltip элементы. Source-level fixes Task 1 + Task 2 присутствуют, но не имеют effect на rendered output. Это library-level limitation, аналогично sub-C — не application defect. Effective a11y покрытие: activator/wrapper elements имеют корректные labels через screen reader (TR row context, table column headers); проблема видна только axe-core который проверяет именно native `<input>` атрибуты.
**Next-step options для заказчика:**
- (1) Принять как known Vuetify limitation (parallel sub-C rationale, document в Открытые_вопросы post-MVP a11y polish).
- (2) Investigate Vuetify deep workarounds: `inputAttrs` prop binding, `:id` + manual `<label for>` rendering, Volar slots для `v-text-field`/`v-switch`/`v-checkbox-btn`.
- (3) Upgrade Vuetify 3.12 → 3.13+ если содержит a11y fixes (требует verification + smoke-tests).
Total residual после Task 4 verification: **16 nodes** (6 deals + 9 supplier-prices + 1 tooltip) — **те же что pre-Task-1/2** (source changes были merged commits но не имеют user-visible a11y effect).
---
(оригинальное содержание Q.DEFER.004 ниже — оставить как historical context)