fix(a11y): Q.DEFER.004 sub-B — AdminSupplierPricesView 9 inputs aria-label

3 supplier rows × 3 form controls (cost_rub v-text-field +
quality_score v-text-field + is_active v-switch) = 9 nodes без label —
axe-core критичная label violation.

Fix: :aria-label='${field} для ${supplier.name}' (e.g. 'Cost (₽) для B1 — Сайты и Звонки').

Test coverage: AdminSupplierPricesView.spec.ts 4-й spec проверяет все 9 ожидаемых
aria-label через DOM query.
This commit is contained in:
Дмитрий
2026-05-13 00:35:05 +03:00
parent d9fc3d92e4
commit c8005e0cfc
2 changed files with 30 additions and 1 deletions
@@ -12,6 +12,7 @@
density="compact"
hide-details
variant="plain"
:aria-label="`Cost () для ${item.name}`"
/>
</template>
<template #[`item.quality_score`]="{ item }">
@@ -24,10 +25,17 @@
density="compact"
hide-details
variant="plain"
:aria-label="`Quality для ${item.name}`"
/>
</template>
<template #[`item.is_active`]="{ item }">
<v-switch v-model="item.is_active" hide-details inset density="compact" />
<v-switch
v-model="item.is_active"
hide-details
inset
density="compact"
:aria-label="`Active для ${item.name}`"
/>
</template>
<template #[`item.actions`]="{ item }">
<v-btn size="small" color="primary" :loading="!!saving[item.id]" @click="save(item)">
@@ -58,4 +58,25 @@ describe('AdminSupplierPricesView', () => {
const inputs = wrapper.findAll('input[type="number"]');
expect(inputs.length).toBeGreaterThanOrEqual(6);
});
it('each input/switch has explicit aria-label combining supplier name + field role', async () => {
const wrapper = mount(AdminSupplierPricesView, { global: { plugins: [vuetify] } });
await new Promise((r) => setTimeout(r, 50));
// 3 suppliers × 3 fields = 9 controls
const expectedLabels = [
'Cost (₽) для B1 — Сайты и Звонки',
'Quality для B1 — Сайты и Звонки',
'Active для B1 — Сайты и Звонки',
'Cost (₽) для B2 — SMS',
'Quality для B2 — SMS',
'Active для B2 — SMS',
'Cost (₽) для B3 — SMS',
'Quality для B3 — SMS',
'Active для B3 — SMS',
];
for (const label of expectedLabels) {
const node = wrapper.find(`[aria-label="${label}"]`);
expect(node.exists(), `aria-label="${label}" not found`).toBe(true);
}
});
});