Playwright + axe-core
import AxeBuilder from '@axe-core/playwright';
// Check for missing accessible names
const results = await new AxeBuilder({ page })
.withRules(['button-name', 'label'])
.analyze();
// Find buttons without labels
const violations = results.violations.filter(
v => v.id === 'button-name'
);
console.log('Buttons without names:', violations);
// Verify specific button has aria-label
const editBtn = page.getByRole('button', {
name: 'Edit document'
});
await expect(editBtn).toBeVisible();Manual Checks
// Get all buttons and check for names
const buttons = await page.$$('button');
for (const button of buttons) {
const ariaLabel = await button.getAttribute('aria-label');
const textContent = await button.textContent();
const ariaLabelledBy = await button.getAttribute(
'aria-labelledby'
);
const hasName = ariaLabel ||
textContent?.trim() ||
ariaLabelledBy;
if (!hasName) {
console.log('Button without accessible name:',
await button.evaluate(el => el.outerHTML)
);
}
}