-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support for WebComponents API #1030
Comments
It'd be interesting to look into which APIs webcomponents.js uses that jsdom doesn't support. If I had to guess, that will be much easier to implement than the full web components spec. That said, it would be pretty cool to implement web components. Probably not as hard as one might think---the specs are relatively small. |
Just had time to dig into this a bit: First off, we don't have Just a bit of info, because I had a bit of time. |
Nice. Should be able to expose Window pretty easily. EventTarget prototype is a bit trickier but seems doable given how we currently implement that stuff; it's been a TODO of mine. |
Okay, patches so far are rather easy:
The next crash of webcomponents.js happens due to us not implementing |
Okay I checked into the Polyfill some more, we need to implement/you need to shim the following:
(non-exhaustive list for now) A start is something like the following: jsdom.env({
file: __dirname + '/index.htm', // refers to webcomponent.js
created: function (err, window) {
jsdom.getVirtualConsole(window).sendTo(console)
window.document.createRange = function () { }
window.getSelection = function () { }
window.Range = function () { }
window.Selection = function () { }
window.CanvasRenderingContext2D = function () { } // Object.getPrototypeOf(require("canvas")(0,0).getContext("2d")) might be better
window.SVGUseElement = window.HTMLUnknownElement
},
done: function (err, window) {
console.log(err[0].data.error);
console.log(window.CustomElements)
},
features: {
ProcessExternalResources: ['script']
}
}); That done, there's some bug in our |
+1 Would love to see WebComponents on jsdom, particularly as Polymer gains in popularity, would be great to be able to test custom elements on a headless system. |
Right now there is no cross-browser definition of web components, so it'd be premature to implement. (We're not just going to copy Chrome.) In the meantime, you can try using Polymer with jsdom. |
@domenic fair enough. Well it's more the support for the WebComponents.js polyfill that I'm after, as that's what Polymer depends on - or |
My understanding is that there are three separate polyfills in question. The one in the OP is separate from Polymer. Then there's the webcomponents.org polyfills, which used to be used in old-Polymer. Then in Polymer 1.0, they have their own polyfills, I think, which aren't really polyfills, but instead alternate libraries that do things kinda web-component-ish. Maybe that is webcomponents-lite though. |
On the WebComponentsJS repo, it says that the |
It's really hard to say without some investigation... looking forward to what you find out. |
Yeah, I think my list of todo tasks is still applicable and required to use the shims. Getting #1227 merged in might make us a lot quicker with implementing standards-compliant interfaces so we can fix the missing ones more quickly. |
I've (probably naively) started working on adding CustomElementsRegistry as a way to understand how jsdom is structured. I added "custom-elements/custom-elements-registry/define.html" to the web platform tests list and it passes when it shouldn't (i haven't implemented nearly enough yet). I'm pretty sure the test isn't really running as even adding a |
Seems like that's caused because we fail in the initial |
That helps very much, thanks! I'll see if I can figure out what is going on there, and if not I'll create a simplified test as you recommended. |
@Sebmaster Just in case your interested, I did a bit of research into what is going on with that test and the results are surprising to me. The test is using the named access feature of html. This means you can do stuff like: <div id="foo"></div>
<script>
console.log(window.foo === document.getElementById('foo'));
</script> However, if the element has a nested browsing context, the global should point to that instead (see the linked spec). For iframe's that's the What's crazy is that Chrome and Firefox get this wrong; the global points to the iframe, not it's contentWindow. Seeing this, I assumed it was a jsdom bug and did some hunting, eventually finding that test, which led me to the spec. tldr; working on jsdom is very educational and you guys do an amazing job. Going to file bugs in the respective browsers. Also will send a PR to web-platform-tests, I found some other mistakes in the test as well. |
This is even more motivation to upstream tests like https://github.com/tmpvar/jsdom/blob/master/test/living-html/named-properties-window.js to WPT. Thank you for posting! It makes me feel really great about jsdom ^_^ |
Hi! I managed to make Custom Elements polyfill work with jsdom by combining
Note: the repo uses jsdom 8.5.0. The reason is that I only had success with a MutationObserver polyfill, that uses Mutation Events internally. Mutation Events were removed after 8.5.0 due to bad performance. If native Mutation Observer comes out I will remove the polyfill and update to the latest jsdom. |
I've got the latest jsdom, and https://github.com/WebReflection/document-register-element is working for me! I've been experimenting with the more official polyfills, and I'm having trouble for some reason. My goal is to get at least custom elements and html imports to work...it would be awesome if we could get Polymer to work as well. |
I can get the Polymer scripts to run without error. I can even create a component and pass it to the Polymer constructor. After that it fails silently. I think shadow DOM is the issue. I've been trying to get the webcomponentsjs HTML imports polyfill to work. I can get the script to run, and I believe my HTML imports execute an xmlhttprequest, but it doesn't seem like the scripts in my imports get run. |
Care to share an example @lastmjs? I'm currently knee deep in web components myself. If I can be of help i'd gladly contribute with you. |
@snuggs Thanks! Give me a day or two, I'm in the middle of some pressing things at the moment. |
Nice, Thanks! |
@majo44 this is not required with latest jsdom. When working with Jest (which is using jsdom v11) you can just use updated environment: https://www.npmjs.com/package/jest-environment-jsdom-fourteen |
@mgibas thanks, with jest-environment-jsdom-fourteen it is also works fine and mutation observer polyfill is not required (but version is 0.1.0, single commit package :) ) |
Is there a breakdown of which of the web components APIs are currently supported by JSDOM? Seems like shadow DOM is supported, but not custom elements (at least in the release branch/repo)? |
@tbranyen do you have the source code for your fork available somewhere? Would be curious to look at the diff 🙂 |
I'm using jest-environment-jsdom-fifteen like @majo44 suggested, and the babel-polyfill and document-register-element (see @mgibas answers). But I still get an error when I try to retrieve my web component shadow dom for tests.
const el;
beforeEach(async() => {
const tag= 'my-component'
const myEl = document.createElement(tag);
document.body.appendChild(myEl);
await customElements.whenDefined(tag);
await new Promise(resolve => requestAnimationFrame(() => resolve()));
el = document.querySelector(tag);
}
it(() => {
const fooContent = el.shadowRoot.querySelectorAll('slot[name=foo] > *');
}) Any idea of a workaround? FYI, it was already tested with Karma, Mocha, Chai & Jasmine. Nothing special in my component: customElements.define(
'my-component',
class extends HTMLElement {
constructor() {
super();
const shadowRoot = this.attachShadow({ mode: 'open' });
...
}
}) Edit I did some debugging with jsdom 15.1.1 in order to better understand my issue. So, Element.shadowRoot is implemented since 88e72ef jsdom/lib/jsdom/living/nodes/Element-impl.js Lines 388 to 415 in 1951a19
After document.createElement, this._shadowDom is ok at https://github.com/jsdom/jsdom/blob/15.1.1/lib/jsdom/living/nodes/Element-impl.js#L403. And every element in the shadow dom is created (Element constructor called with the right values). But when I call Same thing after await customElements.whenDefined(tag);
await new Promise(resolve => requestAnimationFrame(() => resolve())); Or even if I use the following instead of document. document.body.innerHTML = `
<my-component id="fixture"></my-component>
`: For reproduction, see: |
@NMinhNguyen I guess you can find the source code of the fork made by @tbranyan here https://github.com/tbranyen/jsdom/tree/initial-custom-elements-impl |
I'm trying to test web components made with lit-html and lit-element and I noticed this difference when creating the elements. const myElem = new MyElem();
document.body.appendChild(myElem);
await myElem.updateComplete;
console.log(myElem.shadowRoot) // exists and has the rendered markup and when I use the document.createElement const myElem = document.createElement('my-elem');
document.body.appendChild(myElem);
await myElem.updateComplete;
console.log(myElem.shadowRoot) // null For configuring jest I only use one polyfill that is : Seems that the render method in const myElem = document.createElement('my-elem');
myElem.initialize();
document.body.appendChild(myElem);
await myElem.updateComplete;
console.log(myElem.shadowRoot) // exists and has the rendered markup |
I have created an alternative DOM that supports web components. I first tried to make a PR, but the way JSDOM works made it hard for me to solve my needs there. You are free to use it or look at the code. DOM: Jest environment: |
Looks awesome. Thank you.
…On Mon, Oct 7, 2019, 1:08 AM capricorn86 ***@***.***> wrote:
I have created an alternative DOM that supports web components. I first
tried to make a PR, but the way JSDOM works made it hard for me to solve my
needs there. You are free to use it and/or look at the code.
DOM:
https://www.npmjs.com/package/happy-dom
Jest environment:
https://www.npmjs.com/package/jest-environment-happy-dom
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
<#1030?email_source=notifications&email_token=ACQ5ZD5QUEITPND4SXWOHW3QNILSRA5CNFSM4A4G5SF2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEAOO5ZA#issuecomment-538767076>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ACQ5ZDYU465DXI4KHBQH4KTQNILSRANCNFSM4A4G5SFQ>
.
|
@capricorn86 |
Thank you @TechQuery! |
Thank you @motss! |
I'd be interested in this as well :) |
@capricorn86 I was trying to follow your suggestion. and still having a persistent issue with "Custom element not defined" I get a customElements is not defined with the error below: |
Hi @Hlulani! I believe that the correct procedure would be to add a ticket at Happy DOM (if you are using Happy DOM) or Vitest. To answer your question: You need to look into your tests and try to find what could cause code to continue running after the tests has completed. |
Hi @capricorn86 Thanks a lot for your response and I definitely will raise issues in the right places next time, regarding the issue, I was able to solve this by adding adding |
70000 is a long time. I would recommend looking into the tests that are taking such a long time and try to reduce it (perhaps by mocking if they are unit tests). |
We are trying to use jsdom for our unit tests for React core (http://facebook.github.io/react/).
Unfortunately, the web components spec is not natively supported by jsdom, and the webcomponents.js polyfill does not run on jsdom. This issue requests the addition of WebComponent support (custom elements, shadow dom, html imports, etc).
The text was updated successfully, but these errors were encountered: