@testing-library/jest-dom version: 4.1.2node version: 10.15.0npm (or yarn) version: yarn 1.13.0expect(getByTestId('testid')).toHaveAttribute('disabled')
Running a test in a node environment using a JSDOM fragment rather than a full JSDOM container. (This was produced by https://github.com/marko-js/testing-library)
Got the following error:
received value must be an HTMLElement or an SVGElement.
Received has type: object
I tracked it down to this line:
https://github.com/testing-library/jest-dom/blob/master/src/utils.js#L47
There is no defaultView object defined when using a JSDOM fragement.
This is also mentioned in https://github.com/testing-library/dom-testing-library/pull/377, where they question the need to have a window object:
It seems like a valid question. Does jest-dom need to require a global window object?
Cannot use jest-dom within node when using a JSDOM fragment
Remove the requirement for having a defaultView. Or get dom-testing-library to add one.
I'm thinking that the issue here is that the DOM element is not attached to the document which is why this is a problem. I hadn't considered that issue coming up, but it makes sense.
I'm not sure what to do about this. I think this would be solved if we just required that everyone using these libraries have a globally accessible window and document so we didn't have to retrieve that from the DOM elements.
cc @eps1lon thoughts?
@kentcdodds another option would be to walk the constructors prototype chain and check for the name "HTMLElement" or "SVGElement" like so:
function checkHtmlElement(htmlElement, ...args) {
if (
!instanceOf(htmlElement, 'HTMLElement') &&
!instanceOf(htmlElement, 'SVGElement')
) {
throw new HtmlElementTypeError(htmlElement, ...args)
}
}
function instanceOf(obj, name) {
if (obj) {
let constructor = obj.constructor
while (constructor) {
if (constructor.name === name) {
return true
}
constructor = Object.getPrototypeOf(constructor)
}
}
return false
}
But this issue would also present itself in toBeVisible and toHaveStyle.
I think the simplest approach for us from the @marko/testing-library side of things would just be to not use JSDOM.fragment for testing the server rendered markup. This is somewhat lame since In my opinion server side tests shouldn't be able to interact with the window or trigger events (those should happen in a browser context, not on the server side), but at least it would work for the basic cases and require less work on the side of jest-dom.
I would prefer the window and document not to be required globally as this is going to cause the tests in our case to expose these globals even though we are only using jsdom to do some validation on html strings.
I'm fine with that personally.
That works for me too. Thanks @DylanPiercey .
I'll let @kentcdodds close the issue, if you think its not a blocker for other cases where someone may use a JSDOM fragment.
Released @marko/[email protected] which ensures there is a defaultView. So it's all good on our side of things 馃槃.
Looks ok 馃憤
This is my current stance:
jsdom