dom-testing-library version: 3.8.2react version: N/Anode version: v10.11.0 (but it doesn't matter)npm (or yarn) version: yarn 1.10.1 (but it doesn't matter)See the reproduction section below.
<div> containing a <select> with two <option>s.<select> using getBySelectTextchange event on the fetched <select> to select another valid option<select> from the <div> again using the newly selected option's label (child element)The <select> cannot be fetched by its new "select text":
FAIL ./index.test.js
✕ should respond to changes (4520ms)
● should respond to changes
Unable to find a <select> element with the selected option's text: Option 2
<div>
<select>
<option
value="option-1"
>
Option 1
</option>
<option
value="option-2"
>
Option 2
</option>
</select>
</div>
22 | // but this times out because the text hasn't been updated.
23 | // No changes are reflected in the DOM, which is probably why…
> 24 | return waitForElement(() => getBySelectText(container, 'Option 2'));
| ^
25 | });
26 |
at getElementError (node_modules/dom-testing-library/dist/query-helpers.js:29:10)
at getAllBySelectText (node_modules/dom-testing-library/dist/queries.js:375:45)
at firstResultOrNull (node_modules/dom-testing-library/dist/query-helpers.js:37:30)
at getBySelectText (node_modules/dom-testing-library/dist/queries.js:385:42)
at getBySelectText (index.test.js:24:33)
at onMutation (node_modules/dom-testing-library/dist/wait-for-element.js:48:22)
at node_modules/dom-testing-library/dist/wait-for-element.js:66:7
at waitForElement (node_modules/dom-testing-library/dist/wait-for-element.js:26:10)
at Object.waitForElement (index.test.js:24:12)
const { getBySelectText, fireEvent, wait, waitForElement } = require('dom-testing-library');
it('should respond to changes', () => {
const select = document.createElement('select');
select.innerHTML = `
<option value="option-1">Option 1</option>
<option value="option-2">Option 2</option>
`;
const container = document.createElement('div');
container.appendChild(select);
const foundSelectBeforeEvent = getBySelectText(container, 'Option 1');
expect(foundSelectBeforeEvent.value).toBe('option-1');
fireEvent.change(foundSelectBeforeEvent, { target: { value: 'option-2' }});
// It has been updated, and this passes
expect(foundSelectBeforeEvent.value).toBe('option-2');
// I would then expect to be able to get the <select> again by the new text,
// but this times out because the text hasn't been updated.
// No changes are reflected in the DOM, which is probably why…
return waitForElement(() => getBySelectText(container, 'Option 2'));
});
I've tried (among other things):
waiting for a tick to let updates happenfocus and blur before and after firing the change to force a rerenderwaitForElement (it just fails in the same way, but faster)The <select> element doesn't seem to update its displayed value, so it behaves differently from what a user experiences in a browser.
The <select> should be selectable using the label of the selected option. I don't know how to fix it, though :smile:
Hmmm... I'm not sure what's going on here. Would anyone care to dig deeper into this?
I created this and I'm unable to reproduce: https://jsbin.com/lukecehisa/edit?html,js,console
Thanks for checking it out
I'm pretty sure the jsbin snippet works because it executes in the browser, and as I mentioned in the OP, this behaviour for the select is different from the browser.
Would be great if someone could take a look! :smile:
I can reproduce the same error in a Jest/JSDOM environment
Hmmm... Maybe it's a bug in JSDOM :-(
Probably this: https://github.com/jsdom/jsdom/issues/2326, fixed Aug 18
https://github.com/kentcdodds/dom-testing-library/blob/master/src/queries.js#L117
The fix went out in JSDOM 12.0.0 https://github.com/jsdom/jsdom/blob/master/Changelog.md#1200
But I'm seeing jsdom 11.5.1 coming in via jest-environment-jsdom
Ah, in that case I'm pretty sure we'll need an updated version of jsdom which I'm guessing is already in the latest version of Jest 🤔
JSDOM peer is not updated in the Jest repo: https://github.com/facebook/jest/blob/master/packages/jest-environment-jsdom/package.json#L13
@theneva perhaps you could open a PR on Jest to upgrade JSDOM?
In any case, there's not much we can do in this project, so I'm going to go ahead and close this issue. Sorry! 😬
Try adding this to package.json
"resolutions": {
"jsdom": "12.2.0"
}
Didn't seem to work for me but maybe you can figure something out.
We won't upgrade jsdom in jest (for some time) as they've dropped node 6. See e.g. https://github.com/facebook/jest/pull/7122
Ah, that's unfortunate. Any timeframe on when jest can drop node < 8?
Probably not before it's EOL-ed, although we dropped 4 in December 2017. But I wouldn't bet on a PR dropping 6 landing before Christmas
Ok, thanks!
With help from @SimenB I put together a version of jest-environment-jsdom that ships JSDOM version 12:
GitHub: https://github.com/theneva/jest-environment-jsdom-twelve
npm: https://www.npmjs.com/package/jest-environment-jsdom-twelve
Using that solves my issue :smile:
Thanks for looking into this!
Though HTMLSelectElement.selectedOptions is not reactive in the version of JSDOM bundled with Jest, HTMLSelectElement.selectedIndex is.
I wouldn't mind opening a PR to change it to selectedIndex, but that would drop compatibility with the multiple attribute.
@kentcdodds What would you prefer?
Hmmmm.... What if we get the best of all worlds. If the select has multiple then let's use selectedOptions (hopefully they don't need it to be reactive), if it's not multiple then we can use selectedIndex.
Is there any way we could iterate through the...
Yeah, we can do this:
const selectedOptions = Array.from(selectElement.options).filter(option => option.selected)
:tada: This issue has been resolved in version 3.10.1 :tada:
The release is available on:
npm package (@latest dist-tag)Your semantic-release bot :package::rocket:
Most helpful comment
With help from @SimenB I put together a version of jest-environment-jsdom that ships JSDOM version 12:
GitHub: https://github.com/theneva/jest-environment-jsdom-twelve
npm: https://www.npmjs.com/package/jest-environment-jsdom-twelve
Using that solves my issue :smile:
Thanks for looking into this!