user-event
user-event copied to clipboard
The validity state of input is not updated after `user.type`
Reproduction example
https://codesandbox.io/p/sandbox/userevent-dom-djcc7b
Prerequisites
- Render an input with a pattern and a value that matches the pattern. Make sure the css specifies the style based on the
:valid
/invalid
pseudoclass. -
user.type
to change the value of the input to mismatch the pattern. - Query the style to test if it matches the style specified in the css file.
Relevant code:
const css = `
input.test-input:valid {
color: #ffffff;
}
input.test-input:invalid {
color: #000000;
}
`;
test("Test", async () => {
const user = userEvent.setup();
render(
<>
<style>{css}</style>
<input
data-testid="element"
class="test-input"
type="text"
pattern="must-match-this"
value="must-match-this"
/>
</>,
);
await user.type(screen.getByTestId("element"), "aaa");
expect(screen.getByTestId("element")).toHaveStyle("color: rgb(0, 0, 0)"); // Fails
});
Expected behavior
The input element should now have an invalid state.
Actual behavior
The input element still have a valid state
User-event version
14.5.2
Environment
Testing Library framework: @testing-library/[email protected]
Test environment:
[email protected]
DOM implementation: [email protected]
Additional context
A bit clarification why I think this is likely a user-event
bug
If I remove the user.type
line and change the initial value to mismatch the pattern, the style test would pass.
const css = `
input.test-input:valid {
color: #ffffff;
}
input.test-input:invalid {
color: #000000;
}
`;
test("Test", async () => {
const user = userEvent.setup();
render(
<>
<style>{css}</style>
<input
data-testid="element"
class="test-input"
type="text"
pattern="must-match-this"
value="must-match-thisaaa"
/>
</>,
);
expect(screen.getByTestId("element")).toHaveStyle("color: rgb(0, 0, 0)"); // succeeds
});
If I have an initially matched value, but set it to a mismatching value from container, the test also succeeds:
const css = `
input.test-input:valid {
color: #ffffff;
}
input.test-input:invalid {
color: #000000;
}
`;
test("Test", async () => {
const user = userEvent.setup();
const {container} = render(
<>
<style>{css}</style>
<input
data-testid="element"
class="test-input"
type="text"
pattern="must-match-this"
value="must-match-this"
/>
</>,
);
const input = container.querySelector("input.test-input");
input.value = 'must-match-thisaaa';
expect(screen.getByTestId("element")).toHaveStyle("color: rgb(0, 0, 0)"); // succeeds
});
But waitFor
won't help:
const css = `
input.test-input:valid {
color: #ffffff;
}
input.test-input:invalid {
color: #000000;
}
`;
test("Test", async () => {
const user = userEvent.setup();
const {container} = render(
<>
<style>{css}</style>
<input
data-testid="element"
class="test-input"
type="text"
pattern="must-match-this"
value="must-match-this"
/>
</>,
);
const input = container.querySelector("input.test-input");
await user.type(screen.getByTestId("element"), "aaa");
await waitFor(() => expect(screen.getByTestId("element")).toHaveStyle("color: rgb(0, 0, 0)")); // fails
});