Ignore specific element for axe rule in test when using jest-axe

1.1k Views Asked by At

We're using jest-axe to check for accessibility violations. However, an internal library we're using has just updated and introduced an a11y bug that's not due to be fixed for a while, causing our tests to fail. Instead of removing the test altogether, I want to ignore the offending element.

The below isn't my exact test, but a close representation. I'm ignoring the label rule for the element with data-testid="ignore-me" . This allows the test to pass, while still throwing errors for other rules. However, if I add a second bad input to my render method, the test still passes, even though data-testid="i-should-still-fail" isn't included in the selector list, and should throw an error.

Am I missing something here?

it("should have no accessibility violations", async () => {
    //  input with no label
    const { container } = render(
        <div>
            <input type="text" data-testid="ignore-me" />
            <input type="text" data-testid="i-should-still-fail" />
        </div>
    );

    const results = await axe(container, {
        rules: {
            label: {
                enabled: false,
                selector: '[data-testid="ignore-me"]',
            },
        },
    });

    expect(results).toHaveNoViolations();
});
1

There are 1 best solutions below

0
On

It looks like what you're doing may not be what you want. Passing options to the main axe call of jest-axe passes those options directly to axe-core's run options which only allows you to enable or disable a rule completely. So in your case you're disabling the label rule (selector is ignored) and that is why it's not failing at all.

Instead what it looks like you'll need to do is to let axe run without disabling the rule and then filter the results out that you don't want. You can pass the elementRef: true option to axe to allow you access to the html node to do some matching against. If you need to do this often you could create a helper function to remove violations that match the provided selector.

it("should have no accessibility violations", async () => {
    //  input with no label
    const { container } = render(
        <div>
            <input type="text" data-testid="ignore-me" />
            <input type="text" data-testid="i-should-still-fail" />
        </div>
    );

    const results = await axe(container, { elementRef: true });
    labelViolation = results.violations.find(violation => violation.id === 'label');

    // remove the desired node to ignore it
    if (labelViolation) {
      labelViolation.nodes = labelViolation.nodes.filter(node => !node.element.matches('[data-testid="ignore-me"]'));

      // remove the violation if there are no more nodes
      if (!labelViolation.nodes.length) {
        results.violations.splice(results.violations.indexOf(labelViolation), 1);
      }
    }

    expect(results).toHaveNoViolations();
});