jsdom
jsdom copied to clipboard
Focussing an element doesn't trigger the CSS update based on the :focus pseudo class
Dear jsdom team,
I'm trying to achieve the following:
Using the CSS pseudo class :focus
to determine whether an element has the style display: block
or none
. I expect the styling of the sibling component to change, when the controlling component is focused. The same way it happens in the browser.
Basic info:
- Node.js version: 16.13.2
- jsdom version: 16.7.0
Minimal reproduction case
import jsdom from "jsdom";
const dom = new jsdom.JSDOM(`
<html>
<head>
<style>
#focus_input:focus + #focus_label { display: none; }
</style>
</head>
<body>
<div>
<input
id="focus_input"
type="text"
/>
<label id="focus_label">
Focus input to hide
</label>
</div>
</body>
</html>
`);
const { document } = dom.window;
document.getElementById("focus_input").focus();
console.log(document.activeElement);
console.log(document.getElementById("focus_label").style.display); // should print "display: none"
https://codesandbox.io/s/jsdom-focus-sibling-combinator-ph3tql?file=/src/index.js
How does similar code behave in browsers?
In the browser it works as expected. See example
https://codesandbox.io/s/jsdom-focus-sibling-combinator-ph3tql?file=/index.html
Just to be sure, I'm not 100% confident that in the browser it's working as it should. When calling document.getElementById("focus_input").focus();
from the console, the design doesn't really change for me, does that work for you?
@MatanBobi Yes, for me it does work. Using https://codesandbox.io/s/jsdom-focus-sibling-combinator-ph3tql?file=/index.html I can hide the sibling item through focusing the input via console.
https://user-images.githubusercontent.com/64063903/165035748-7e8aa663-73db-4a29-bb95-01bd9ae06793.mov
Try opening a new window button and use the browser console to run document.getElementById("focus_input").focus();
. The label did not disappear for me on Chrome Version 101.0.4951.67
Try opening a new window button and use the browser console to run
document.getElementById("focus_input").focus();
. The label did not disappear for me on Chrome Version 101.0.4951.67
@Vac1911 That is interesting/worrying. Because it does work in the original window. And it still works when I actually click inside input_focus
or focus it via TAB
. But did you realise, that input_focus
doesn't get a focus when calling document.getElementById("focus_input").focus();
? Because it also doesn't get its focus outline.
So to me it seems that HTMLElement.focus()
is simply not working correctly in the new window version of the app.
But did you realise, that input_focus doesn't get a focus when calling document.getElementById("focus_input").focus();?
@tbelch-at-eHealth-Tec Yes that's what I was trying to communicate. As far as I know Element.focus()
does not trigger :focus
, I'm not sure why it does it in codesandbox.
I'm having a similar issue. I have an input with a gray border, when I focus I change it to black:
export const Input = styled.input`
border-color: gray;
:focus {
border-color: black;
}
`
When testing this input, hoping it has focus, it works
it('should have a specif border color when focused', async () => {
const user = userEvent.setup()
await user.click(screen.queryByRole('textbox'))
expect(screen.queryByRole('textbox')).toHaveFocus()
})
But when I add the expectation that the style applies to the focus:
it('should have a specif border color when focused', async () => {
const user = userEvent.setup()
await user.click(screen.queryByRole('textbox'))
expect(screen.queryByRole('textbox')).toHaveFocus()
expect(screen.queryByRole('textbox')).toHaveStyle(`border-color: black;`)
})
I get that:
You can see that the .toHaveFocus
succeeded but the style did not
I have the same problem as the fine people above ☝️
Look like this is related to https://github.com/dperini/nwsapi logic, but from my investigations, this moment should be fine.
-
:hover
is stateful and might not work if there is no focused element at style parsing time -
:focus-within
is broken - https://github.com/dperini/nwsapi/pull/74
UPD: Just update
nwsapi