Skip to content

toHaveErrorMessage #256

Closed
Closed
@jacobparis

Description

@jacobparis

Describe the feature you'd like:

I'd like an assertion for the aria-errormessage attribute. It accepts a list of id strings formatted identically to the format aria-describedby accepts.

https://www.w3.org/TR/wai-aria-1.1/#aria-errormessage

Browser support was poor a year ago but I can't seem to find any up-to-date information on its support level. There is some chance that this is unsupported enough to be not worth implementing, but on a long enough timeline I think it'll fit well here.

Usage

<input
  type="text"
  id="mortgage-amount"
  name="MORTGAGE_AMOUNT"
  aria-label="Mortgage Amount"
  aria-describedby="mortgage-amount-description"
  aria-invalid="true"
  aria-errormessage="mortgage-amount-error"
/>

<p id="mortgage-amount-error"> Must be a positive number </p>
expect().toHaveErrorMessage('Must be a positive number')

Suggested implementation:

The implementation would be nearly a clone of toHaveDescription except the elements it reads come from the aria-errormessage attribute instead of aria-describedby

It could also assert that aria-invalid is true

I'm willing to make a PR for inclusion but I'm new to open source so I wanted to get feedback up front

Describe alternatives you've considered:

Teachability, Documentation, Adoption, Migration Strategy:

toHaveErrorMessage

toHaveErrorMessage(text: string | RegExp)

This allows you to check whether the given element has an error message or not.

An element gets its error message via the
aria-errormessage attribute.
Set this to the id of one or more other elements. These elements may be nested
inside, be outside, or a sibling of the passed in element.

Whitespace is normalized. Using multiple ids will
join the referenced elements’ text content separated by a space.

When a string argument is passed through, it will perform a whole
case-sensitive match to the error message text.

To perform a case-insensitive match, you can use a RegExp with the /i
modifier.

To perform a partial match, you can pass a RegExp or use
expect.stringContaining("partial string").

Examples

<!-- with aria-errormessage and aria-invalid -->
<input type="text" aria-label="Username" aria-errormessage="username-error" aria-invalid="true"/>

<div id="username-error">
  Username must not contain spaces
</div>

<!-- with just aria-errormessage -->
<input type="text" aria-label="Email" aria-errormessage="email-error" />

<div id="email-error">
  Email must contain an '@' sign
</div>

<!-- with just aria-invalid -->
<input type="password" aria-label="Password" aria-invalid="true" />
// with aria-errormessage and aria-invalid
const usernameInput = getByLabelText('Username')

expect(usernameInput).toHaveErrorMessage('Error: Username must not contain spaces')
expect(usernameInput).toHaveErrorMessage(/Error/) // to partially match
expect(usernameInput).toHaveErrorMessage(expect.stringContaining('Error') // to partially match
expect(usernameInput).toHaveErrorMessage(/error/i) // to use case-insensitive match
expect(usernameInput).not.toHaveErrorMessage('Other error message')

// with just aria-errormessage
const emailInput = getByLabelText('Email')

expect(emailInput).not.toHaveErrorMessage()
expect(emailInput).not.toHaveErrorMessage('') // Missing aria-invalid will return false

// with just aria-invalid
const passwordInput = getByLabelText('Password')

expect(passwordInput).not.toHaveErrorMessage()
expect(passwordInput).toHaveErrorMessage('') // Missing or empty error message always becomes a blank string, 

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions