Jsdom: Dukungan untuk WebComponents API

Dibuat pada 17 Feb 2015  ·  89Komentar  ·  Sumber: jsdom/jsdom

Kami mencoba menggunakan jsdom untuk pengujian unit kami untuk React core (http://facebook.github.io/react/).

Sayangnya, spesifikasi komponen web tidak didukung secara asli oleh jsdom, dan polyfill webcomponents.js tidak berjalan di jsdom. Masalah ini meminta penambahan dukungan WebComponent (elemen kustom, shadow dom, impor html, dll).

feature

Komentar yang paling membantu

TL;DR

Saya bekerja selama 2 minggu terakhir untuk mengevaluasi kelayakan untuk menambahkan dukungan untuk elemen khusus di jsdom. Berikut hasil investigasinya.

Anda dapat menemukan implementasi elemen kustom yang sesuai dengan spesifikasi di sini: https://github.com/jsdom/jsdom/compare/master...pmdartus :custom-elements?expand=1. Masih ada beberapa tepi kasar di sana-sini, tetapi setidaknya sebagian besar lulus uji WPT . Tes gagal yang tersisa adalah masalah JSDOM yang diketahui atau masalah kecil yang dapat ditangani saat kami akan menangani implementasi aktual di jsdom.

Sekarang inilah kabar baiknya, sekarang Shadow DOM didukung secara asli, dengan cabang elemen kustom dan pengamat mutasi, saya dapat memuat dan merender versi terbaru dari contoh aplikasi hello world Polymer 3 di jsdom . Dalam statusnya saat ini, cabang tidak dapat memuat aplikasi Stensil (mode pengembangan Stensil memerlukan beberapa fitur yang tidak didukung seperti module , dan mode prod muncul karena alasan yang tidak diketahui).

Rencana aksi

Berikut adalah daftar perubahan yang perlu terjadi terlebih dahulu, mulai menangani implementasi spesifikasi elemen kustom yang sebenarnya. Setiap item dalam daftar adalah independen dan dapat ditangani secara paralel.

Dukungan untuk atribut tambahan IDL [CEReactions]

Salah satu inti yang secara fungsional hilang di jsdom untuk menambahkan dukungan untuk elemen khusus adalah atribut [CEReactions] . Saya sebagian dapat mengatasi masalah ini dengan menambal properti prototipe yang tepat. Pendekatan ini berfungsi selama tumpukan reaksi elemen khusus bersifat global dan bukan per unit konteks penelusuran asal serupa yang terkait karena semua prototipe antarmuka dibagikan.

Pendekatan ini memiliki beberapa kekurangan karena beberapa antarmuka memiliki atribut [CEReactions] yang terkait dengan properti yang diindeks ( HTMLOptionsCollection , DOMStringMap ). Secara internal, jsdom menggunakan Proksi untuk melacak mutasi ke properti tersebut. Penambalan prototipe antarmuka tidak berfungsi dalam kasus ini. Pendekatan lain, untuk mengatasi masalah ini adalah dengan menambal implementasi alih-alih antarmuka (tidak diimplementasikan).

Saya tidak cukup akrab dengan internal webidl2js, tetapi kita harus menjelajahi menambahkan kait global untuk [CEReactions] ?

Perubahan:

Dukungan untuk atribut tambahan IDL [HTMLConstructor]

Seperti yang dijelaskan @domenic di atas , menambahkan dukungan untuk [HTMLConstructor] adalah salah satu pemblokir utama di sini.

Saya dapat mengatasi masalah ini di sini dengan menambal konstruktor antarmuka untuk setiap konteks penelusuran. Konstruktor antarmuka akan dapat mengakses jendela kanan dan objek dokumen sambil menjaga prototipe bersama. Pendekatan ini juga menghindari overhead kinerja untuk mengevaluasi kembali prototipe antarmuka untuk setiap konteks penelusuran baru.

Saya tidak yakin apakah ini pendekatan terbaik di sini, tetapi ini sesuai dengan persyaratan tanpa memperkenalkan overhead kinerja tambahan.

Perubahan:

Jadikan spesifikasi algoritme penguraian make fragmen sesuai (#2522)

Seperti yang dibahas di sini , implementasi algo penguraian fragmen HTML yang digunakan dalam Element.innerHTML dan Element.outerHTML salah. Algo parsing perlu di-refactored, agar callback reaksi elemen kustom dipanggil dengan benar.

Perubahan:

Tingkatkan pencarian antarmuka untuk membuat elemen algo

Salah satu masalah yang dengan cepat saya temukan, adalah pengenalan dependensi melingkar baru saat menambahkan dukungan untuk pembuatan elemen kustom. Baik CustomElementRegistry dan algoritma create elemen membutuhkan akses ke antarmuka Element, menciptakan mimpi buruk dependensi melingkar.

Pendekatan yang diambil di cabang adalah untuk membuat InterfaceCache , yang akan memungkinkan pencarian antarmuka oleh namespace elemen dan nama tetapi juga dengan nama antarmuka. Modul antarmuka dievaluasi dan di-cache dengan malas setelah dievaluasi. Pendekatan ini menghilangkan ketergantungan melingkar karena antarmuka tidak lagi diperlukan di tingkat atas.

Ini adalah salah satu pendekatan untuk menyelesaikan masalah lama di jsdom, salah satu masalah ini dengan pendekatan ini adalah bahwa hal itu mungkin akan merusak versi webpacked/browser dari jsdom (tidak diuji).

Perubahan:

~Perbaiki Element.isConnected untuk mendukung Shadow DOM (https://github.com/jsdom/jsdom/pull/2244)~

Ini adalah masalah yang muncul dengan pengenalan DOM bayangan , isConnected mengembalikan false jika elemen tersebut adalah bagian dari pohon bayangan. Tes WPT baru perlu ditambahkan di sini, karena tidak ada tes yang memeriksa perilaku ini.

Perubahan:

Perbaiki dokumen simpul HTMLTemplateElement.templateContents (#2426)

Konten template seperti yang didefinisikan dalam spesifikasi memiliki dokumen simpul yang berbeda dari HTMLTemplateElement itu sendiri. jsdom tidak mengimplementasikan perilaku ini hari ini dan HTMLTemplateElement dan konten templatnya berbagi hal yang sama
simpul dokumen.

Perubahan:

  • HTMLTemplateElement-impl.js
  • htmltodom.js . Perubahan ini juga memiliki beberapa efek hilir pada parser. Jika elemen konteks adalah HTMLTemplateElement, algoritma penguraian fragmen HTML harus mengambil simpul dokumen dari konten template dan bukan dari elemen itu sendiri.

Tambahkan langkah- langkah adopsi yang tidak ada ke HTMLTemplateElement (#2426)

HTMLTemplateElement perlu menjalankan beberapa langkah spesifik saat diadopsi ke dokumen lain. Sejauh yang saya tahu, antarmuka tanah memiliki langkah adopsi khusus. Implementasi algoritma node adopsi juga perlu diperbarui untuk menjalankan langkah adopsi ini.

Perubahan:

Tambahkan dukungan untuk pencarian isValue di parse5 serializer

Fragmen HTML serialisasi juga, ketika membuat serial Elemen mencari nilai is yang terkait dengan elemen dan mencerminkannya sebagai atribut dalam konten serial. Akan menarik untuk menambahkan kait lain di adaptor pohon parse5, yang akan mencari nilai is yang terkait dengan elemen getIsValue(element: Element): void | string .

Pendekatan alternatif (tidak diterapkan) adalah menambahkan perubahan perilaku dari kait getAttrList saat ini untuk mengembalikan nilai is ke daftar atribut, jika elemen memiliki nilai is yang terkait.

Pertunjukan

Sebelum melakukan optimasi kinerja, saya juga ingin memeriksa kinerja perubahan di cabang. Penambahan elemen khusus menambahkan overhead kinerja 10% dibandingkan dengan hasil saat ini pada master untuk tolok ukur mutasi pohon. Namun pembuatan lingkungan JSDOM baru sekarang 3x hingga 6x lebih lambat dibandingkan dengan master, itu akan membutuhkan penyelidikan lebih dalam untuk mengidentifikasi akar masalahnya.

Lebih detail: di sini

Semua 89 komentar

Akan menarik untuk melihat API mana yang digunakan webcomponents.js yang tidak didukung oleh jsdom. Jika saya harus menebak, itu akan jauh lebih mudah diimplementasikan daripada spesifikasi komponen web lengkap.

Yang mengatakan, akan sangat keren untuk mengimplementasikan komponen web. Mungkin tidak sesulit yang dibayangkan --- spesifikasinya relatif kecil.

Hanya punya waktu untuk menggali ini sedikit:

Pertama, kita tidak memiliki Window yang didefinisikan dalam lingkup jendela. Saya baru saja menambal ini dengan this.Window = this.prototype di konstruktor Window .
Kedua, webcomponentsjs mengharapkan Window memiliki prototipe lain, yaitu prototipe EventTarget , yang tidak kami implementasikan sebagai entitas terpisah.

Sekedar info, karena saya punya sedikit waktu.

Bagus. Seharusnya bisa mengekspos Window dengan cukup mudah. Prototipe EventTarget sedikit lebih rumit tetapi tampaknya bisa dilakukan mengingat bagaimana kami saat ini mengimplementasikan hal itu; itu adalah TODO saya.

Oke, patch sejauh ini agak mudah:

  • [x] this.Window = Window; di konstruktor Jendela
  • [x] inherits(dom.EventTarget, Window, dom.EventTarget.prototype); setelah definisi Window

Kerusakan berikutnya dari webcomponents.js terjadi karena kami tidak mengimplementasikan HTMLUnknownElement (#1068), setelah shiming bahwa kami perlu mengimplementasikan SVGUseElement . Itulah yang saat ini saya blokir, karena webcomponents.js tampaknya tidak menyukai SVGUseElement yang disamarkan oleh HTMLDivElement dan memberikan pernyataan.

Oke saya memeriksa Polyfill lagi, kita perlu menerapkan/Anda perlu shim berikut:

  • [x] HTMLUnknownElement #1068
  • [ ] SVGUseElement
  • [ ] window.CanvasRenderingContext2D
  • [ ] Rentang API (termasuk: document.getRange() , window.getSelection() , window.Range , window.Selection ; #804 mungkin merupakan permulaan)
  • [ ] npm i canvas

(daftar tidak lengkap untuk saat ini)

Awal adalah sesuatu seperti berikut:

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']
  }
});

Selesai, ada beberapa bug di konstruktor HTMLDocument kami, yang menyebabkan kesalahan tumpukan panggilan maksimum. Konstruktor saat ini hanya untuk penggunaan internal, namun valid bahwa beberapa skrip di situs membuat panggilan ke sana sehingga kami perlu membuat konstruktor tersebut tersedia untuk konsumsi publik.

+1 Akan senang melihat Komponen Web di jsdom, terutama karena popularitas Polimer, akan sangat bagus untuk dapat menguji elemen khusus pada sistem tanpa kepala.

Saat ini tidak ada definisi lintas-browser dari komponen web, jadi akan terlalu dini untuk diterapkan. (Kami tidak hanya akan menyalin Chrome.) Sementara itu, Anda dapat mencoba menggunakan Polymer dengan jsdom.

@domenic cukup adil. Yah, itu lebih merupakan dukungan untuk polyfill WebComponents.js yang saya cari, karena itulah yang bergantung pada Polymer - atau webcomponents-lite (polyfill semuanya kecuali Shadow DOM) saat ini. Melakukan beberapa upaya untuk membuat Polimer bekerja di jsdom, tetapi sejauh ini tidak berhasil - saya berasumsi tugas @Sebmaster dalam komentar di atas setidaknya perlu ditambal terlebih dahulu.

Pemahaman saya adalah bahwa ada tiga polyfill terpisah yang dimaksud. Yang di OP terpisah dari Polymer. Lalu ada polyfill webcomponents.org, yang dulu digunakan di Polymer lama. Kemudian di Polymer 1.0, mereka memiliki polyfill mereka sendiri, saya pikir, yang sebenarnya bukan polyfill, tetapi perpustakaan alternatif yang melakukan hal-hal yang agak web-component-ish. Mungkin itu adalah webcomponents-lite.

Pada repo WebComponentsJS , dikatakan bahwa webcomponentsjs-lite adalah varian , menyediakan polyfill untuk semua _but_ Shadow DOM, yang kemudian secara independen dicoba oleh Polymer untuk dishim menggunakan sistem Shady DOM mereka. Jadi dari itu saya cukup yakin Polymer mengandalkan WebComponents sebanyak mungkin, dengan polyfill WebComponentsJS melakukan pekerjaan kasar. Versi lite seharusnya secara signifikan lebih ringan (cukup lucu ..) jadi saya akan melihat apakah saya dapat menunjukkan dengan tepat apa yang dibutuhkan jsdom untuk versi lite. Menurut Anda, apa peluang agar polyfill (lite atau penuh) berfungsi di jsdom?

Sangat sulit untuk mengatakan tanpa penyelidikan... menantikan apa yang Anda temukan.

Ya, saya pikir daftar tugas yang harus saya lakukan masih berlaku dan diperlukan untuk menggunakan shim. Menggabungkan #1227 mungkin membuat kami jauh lebih cepat dengan menerapkan antarmuka yang sesuai standar sehingga kami dapat memperbaiki yang hilang lebih cepat.

Saya (mungkin secara naif) mulai bekerja menambahkan CustomElementsRegistry sebagai cara untuk memahami bagaimana jsdom disusun. Saya menambahkan "custom-elements/custom-elements-registry/define.html" ke daftar pengujian platform web dan lulus ketika seharusnya tidak (saya belum cukup menerapkannya). Saya cukup yakin tes tidak benar-benar berjalan karena bahkan menambahkan throw di bagian atas tes tidak akan mencegahnya lulus. Jadi saya jelas melewatkan sesuatu; selain menambahkan tes di test/web-platform-tests/index.js apakah ada hal lain yang perlu saya lakukan?

Sepertinya itu disebabkan karena kita gagal di baris const testWindow = iframe.contentDocument.defaultView; awal karena contentDocument tidak terdefinisi karena alasan tertentu. Mungkin ada masalah dengan urutan pemuatan vs. eksekusi skrip kami, tetapi belum membahasnya. Harapan yang membantu Anda bekerja di sekitar itu. Kami mungkin harus menyederhanakan tes untuk tujuan kami (untuk saat ini).

Itu sangat membantu, terima kasih! Saya akan melihat apakah saya dapat mengetahui apa yang terjadi di sana, dan jika tidak, saya akan membuat tes yang disederhanakan seperti yang Anda sarankan.

@Sebmaster Kalau-kalau Anda tertarik, saya melakukan sedikit riset tentang apa yang terjadi dengan tes itu dan hasilnya mengejutkan saya.

Pengujian menggunakan fitur akses bernama html . Ini berarti Anda dapat melakukan hal-hal seperti:

<div id="foo"></div>
<script>
  console.log(window.foo === document.getElementById('foo'));
</script>

_Namun_, jika elemen memiliki konteks penelusuran bersarang, global harus menunjuk ke sana (lihat spesifikasi tertaut). Untuk iframe itu adalah contentWindow . jsdom melakukan ini dengan benar, bahkan ada test . Safari juga melakukannya dengan benar.

Yang gila adalah bahwa Chrome dan Firefox melakukan kesalahan ini; titik global ke iframe, bukan contentWindow. Melihat ini, saya berasumsi itu adalah bug jsdom dan melakukan perburuan, akhirnya menemukan tes itu, yang membawa saya ke spec.

tldr; bekerja di jsdom sangat mendidik dan kalian melakukan pekerjaan yang luar biasa.

Pergi ke file bug di browser masing-masing. Juga akan mengirim PR ke web-platform-tes, saya menemukan beberapa kesalahan lain dalam tes juga.

Ini bahkan lebih memotivasi untuk tes hulu seperti https://github.com/tmpvar/jsdom/blob/master/test/living-html/named-properties-window.js ke WPT. Terima kasih telah memposting! Itu membuat saya merasa sangat hebat tentang jsdom ^_^

Hai!

Saya berhasil membuat polyfill Elemen Kustom berfungsi dengan jsdom dengan menggabungkan

Catatan: repo menggunakan jsdom 8.5.0. Alasannya adalah saya hanya berhasil dengan polyfill MutationObserver, yang menggunakan Mutation Events secara internal. Acara Mutasi dihapus setelah 8.5.0 karena kinerja yang buruk. Jika Pengamat Mutasi asli keluar, saya akan menghapus polyfill dan memperbarui ke jsdom terbaru.

Saya mendapatkan jsdom terbaru, dan https://github.com/WebReflection/document-register-element berfungsi untuk saya! Saya telah bereksperimen dengan polyfill yang lebih resmi, dan saya mengalami masalah karena suatu alasan. Tujuan saya adalah untuk mendapatkan setidaknya elemen kustom dan impor html untuk bekerja...akan luar biasa jika kita bisa mendapatkan Polimer untuk bekerja juga.

Saya bisa menjalankan skrip Polimer tanpa kesalahan. Saya bahkan dapat membuat komponen dan meneruskannya ke konstruktor Polimer. Setelah itu gagal secara diam-diam. Saya pikir shadow DOM adalah masalahnya.

Saya telah mencoba agar polyfill impor webcomponentsjs HTML berfungsi. Saya bisa menjalankan skrip, dan saya yakin impor HTML saya menjalankan permintaan xmlhttp, tetapi sepertinya skrip dalam impor saya tidak dijalankan.

Mau berbagi contoh @lastmjs? Saat ini saya sendiri sedang mempelajari komponen web. Jika saya dapat membantu saya akan dengan senang hati berkontribusi dengan Anda.

@snuggs Terima kasih! Beri saya satu atau dua hari, saya berada di tengah-tengah beberapa hal yang mendesak saat ini.

@snuggs Jika kita bisa membuat webcomponents-lite polyfill bekerja, kita harus bisa menggunakan Polymer. Shadow DOM tampaknya merupakan polyfill yang paling sulit untuk bekerja sejauh ini, dan jika kita menggunakan webcomponents-lite kita tidak perlu khawatir tentang itu untuk saat ini, karena kita akan memiliki akses ke template , custom elements , dan HTML imports .

Saya bisa membuat impor HTML berfungsi dengan polyfill webcomponents-lite . Saya mengalami beberapa perilaku aneh, kemudian saya menemukan ini: https://github.com/Polymer/polymer/issues/1535 Sepertinya impor HTML hanya dapat dimuat melalui protokol non-file yang diaktifkan cors. Jadi saya memutar server http cepat di direktori root proyek saya:

npm install -g http-server
http-server --cors

Dan ini adalah kode dasar yang telah saya kerjakan:

const jsdom = require('jsdom');

const doc = jsdom.jsdom(`
    <!DOCTYPE html>

    <html>
        <head>
            <script src="bower_components/webcomponentsjs/webcomponents-lite.js"></script>
            <link rel="import" href="http://localhost:8080/bower_components/polymer/polymer.html">
        </head>

        <body>
            <test-app></test-app>

            <dom-module id="test-app">
                <template>
                </template>

                <script>
                    setTimeout(() => {
                        class TestApp {
                            beforeRegister() {
                                this.is = 'test-app';
                                console.log('before register');
                            }

                            ready() {
                                console.log('ready');
                            }

                            created() {
                                console.log('created');
                            }

                            attached() {
                                console.log('attached');
                            }
                        }

                        Polymer(TestApp);
                    }, 1000);
                </script>
            </dom-module>
        </body>
    </html>
`, {
    virtualConsole: jsdom.createVirtualConsole().sendTo(console)
});

Untuk beberapa alasan saya harus membungkus instance TestApp dalam setTimeout . Sepertinya impor HTML Polimer tidak memblokir rendering HTML lainnya, jadi tanpa setTimeout konstruktor Polimer tidak ditentukan. Apakah itu perilaku normal untuk impor HTML?

beforeRegister dipanggil, jadi konstruktor Polimer melakukan sesuatu. Jadi sekarang kita telah mendapatkan impor HTML secara efektif, tentu saja template bekerja dengan polyfill webcomponents-lite . Saya tidak yakin bagaimana kinerja polyfill elemen kustom.

Ketika saya memasukkan ke dalam kelas TestApp metode ready atau created , mereka tidak dipanggil. Sepertinya peristiwa siklus hidup tidak ditangani dengan benar. Akar dari masalah itu mungkin dalam penerapan polyfill elemen kustom. Aku akan terus bermain-main.

Potensi masalah yang harus dipecahkan:

  • [ ] Impor HTML tidak memblokir dengan benar
  • [ ] elemen kustom polyfill berfungsi atau tidak?
  • [ ] Metode siklus hidup polimer tidak dipanggil

Lebih banyak mengutak-atik mengarah ke lebih banyak wawasan. Saya pikir urutan impor dan pendaftaran mungkin mengacaukan segalanya bagi kita. Ketika saya menjalankan const testApp = document.createElement('test-app'); setelah konstruktor Polimer dipanggil, metode created dan ready dipanggil, tetapi bukan metode attached . Mungkin jsdom tidak menangani literal elemen khusus dengan benar? Juga, bahkan saat memanggil document.body.appendChild(testApp) , metode siklus hidup attached tidak pernah dipanggil.

Ini mungkin membantu memahami urutan pemuatan: https://github.com/webcomponents/webcomponentsjs#helper -utilities

@lastmjs Saat ini saya sedang membalik koin antara CustomElementRegistry.define() dan document.registerElement() . Saya melihat Domenic telah memberikan beberapa masukan yang bagus dan menggabungkan beberapa pekerjaan relatif terhadap whatwg (https://github.com/whatwg/html/issues/1329) Sepertinya ada migrasi API yang sedang berlangsung. Misalnya saya percaya spesifikasi memanggil connectedCallback yang dipasangkan dengan fungsionalitas attachedCallback . Juga dengan asumsi Anda bermaksud attachedCallback ketika Anda mengatakan attached karena penangan itu bukan bagian dari API. Saya telah mengalami define() dan registerElement() masing-masing menembakkan panggilan balik yang berbeda untuk setiap metode. Saya telah menemukan strategi elemen khusus. HTMLImports Domenic disebutkan sebelum implementasi yang menggunakan patch XMLHTTPRequest. Saya percaya dapat mengonversi langsung ke DocumentFragment langsung dari respons. Bau seperti itu bisa jadi minyak ular dengan "impor". Impor "palsu" mungkin di mana kewarasan hidup.

Tampaknya juga ada beberapa tipu muslihat dengan super() dipanggil pada HTMLElement saat melakukan transpiling dari ES6 -> ES5 jadi pantau terus. Saya telah mengalami ini dengan Rollup.js/Babel dan terpaksa menggunakan shim (ringan) dari paket komponen web.
https://developers.google.com/web/fundamentals/getting-started/primers/customelements

Terakhir sepertinya saya mendapatkan (lebih) sukses ketika saya membuat dengan tag prototipe.

document.createElement('main', 'test-app')

Seperti yang @domenic sebutkan kepada saya sebelumnya, kami ingin berhati-hati dalam menerapkan spesifikasi common denominator terendah dan tidak hanya melakukan apa yang dilakukan GOOGLE. Sepertinya garisnya kabur dengan komponen web. Tapi aku penggemar.

Metode apa yang telah Anda kerjakan?

Sejauh ini saya lebih banyak bermain dengan webcomponents-lite polyfill saja, dan Polymer < 2.0. Jadi ketika saya menyebutkan metode attached yang saya maksud adalah metode siklus hidup Polimer yang mereka gunakan alih-alih attachedCallback . Juga, sejauh yang saya ketahui, polyfill belum beralih ke spesifikasi elemen kustom v1 yang baru. Jadi semua yang saya mainkan hanya dengan harapan membuat Polymer bekerja dengan polyfill saat ini.

@snuggs Apakah Anda menggunakan polyfill sekarang atau sedang mengerjakan implementasi aktual di jsdom?

@lastmjs Saya tidak menggunakan polyfill karena saya merasa tidak perlu mendapatkan 80%. Platform ini cukup matang sekarang sehingga dengan sedikit penyesuaian di muka, Anda dapat menggunakan konstruksi asli. Saya suka menggunakan alat yang ringan (biasanya digulung dengan tangan) alih-alih kerangka kerja. Yang mengatakan itu bukan kebanyakan orang. Tampaknya maksud yang dimiliki Domenic adalah Elemen Kustom 👍 impor html tetapi tidak ada masalah dalam memperluas XMLHTTPRequest untuk menangani fetching dari dokumen yang akan membawa kita ke sana. Itu sekitar 6 bulan yang lalu. Banyak yang telah berubah sejak dalam implementasi. Sangat mungkin berpikir. Jadi di mana kita menyelesaikan @lastmjs?

@snuggs Mungkin hal yang paling waras dan tahan masa depan untuk dilakukan adalah mengimplementasikan dukungan kelas satu untuk Elemen Kustom dan Shadow DOM di jsdom. Kedua standar berada di v1 dan sepertinya dari apa yang saya dengar sebagian besar browser utama akan menerapkannya. Bagaimana kita harus melakukan ini? Saya memiliki waktu yang terbatas sekarang, tetapi mungkin kita dapat menjelaskan apa yang perlu dilakukan setidaknya. @domenic Apakah Anda punya saran tentang cara melanjutkan implementasi ini, atau alasan apa pun mengapa kami tidak melakukannya?

Tidak ada saran konkrit dari saya, selain hanya mengimplementasikan spek :)

Saya memiliki cabang tempat saya mengerjakan ini beberapa waktu lalu (spesifikasi telah berubah sedikit sejak saat itu). Menerapkan CustomElementsRegistry cukup mudah, di mana saya berjuang mencari tahu bagaimana menenun reaksi elemen kustom ke dalam basis kode dan kapan itu harus dipanggil dan dari mana. Jika saya mengambil kembali ini (tidak ada janji) itu mungkin yang akan saya fokuskan.

@matthewp Kedengarannya membantu, di mana saya dapat menemukan cabang itu?

@matthewp ya itu akan menyenangkan

https://github.com/matthewp/jsdom/commits/custom-elements seperti yang saya katakan, spesifikasinya berubah sejak saat itu, jadi sudah ketinggalan zaman. Dan ini adalah bagian termudah, tetapi ini adalah titik awal jika ada yang menginginkannya. @snuggs @lastmjs

(http://jonrimmer.github.io/are-we-componentized-yet/)

Secara pribadi hanya mendukung elemen Kustom sudah bagus.

(Perhatikan bahwa pemahaman saya adalah bahwa phantomJS 2.5 harus mendukung setidaknya Template dan mungkin elemen Kustom saat mereka pindah ke versi Webkit yang lebih baru, tidak yakin yang mana).

Sebenarnya, saya mengejek customElements, menggunakan lib document-register-element

const {before} = require('mocha')

before(mockDOM)
before(mockCustomElements)

function mockDOM() {
  const {JSDOM: Dom} = require('jsdom')
  const dom = new Dom('<!doctype html><html><body></body></html>')
  global.document = dom.window.document
  global.window = document.defaultView
  window.Object = Object
  window.Math = Math
}

function mockCustomElements() {
  require('document-register-element/pony')(window)
}

Luar biasa, apakah Anda punya masalah?

sampai sekarang belum ada :D

tapi saya perlu menulis lebih banyak spesifikasi, mencakup lebih banyak hal untuk merasa lebih baik

Luar biasa melihat ada jalan. Sebanyak saya suka polimer, setu tes adalah neraka dan memiliki jsdom sebagai fallback bagus ;) Terima kasih telah memasukkan pekerjaannya

Sepertinya ada PR yang bergerak maju! https://github.com/tmpvar/jsdom/pull/1872

Sebenarnya, saya mengejek customElements, menggunakan lib document-register-element @darlanmendonca

Harus membaca tautan ini tentang melampirkan jsdom global ke node global. Ini anti-pola.

Halo semua,
Saya agak bingung tentang status menjalankan Polimer di dalam JSDOM (menggunakan Node.js 6.7.0 dan JSDOM 11.1.0). Saya sudah mencoba berbagai hal, dengan hasil yang beragam. Saya akan sangat berterima kasih jika seseorang bisa mengisi saya di sini...

Apa yang saya lakukan sejauh ini:

1) Saya menjalankan server http dari direktori root saya

./node_modules/http-server/bin/http-server --cors

2) Saya memuat salah satu komponen Polimer saya ke JSDOM:

jsdom.JSDOM.fromURL("http://localhost:8080/path/to/my-component.html",
  { runScripts: "dangerously",
    resources: "usable"
  })
.then(function (dom) {
  setTimeout(() => {
    window = dom.window;
    component = window.document.querySelector("my-component");
  }, 10000);
})

(Saya juga mencoba memuat file komponen dari sistem file, dengan hasil yang sama.)

3) Ini adalah kode komponen saya:

<!DOCTYPE html>
<html>
<head>
  <script src="/bower_components/webcomponentsjs/webcomponents-lite.js"></script>
</head>

<body>
<link rel="import" href="/bower_components/polymer/polymer.html">
<dom-module id="order-app">
  <template>
    <h1>Hello Polymer</h1>
  </template>

  <script>
    console.log("javascript is being executed");
    addEventListener('WebComponentsReady', function () {
      console.log("web components are ready");
      Polymer({
        is: 'order-app'
      });
    });
  </script>
</dom-module>
</body>
</html>

(Saya menambahkan kepala HTML untuk memuat polyfill komponen web.)

Apa yang bisa saya amati?

Ketika saya menjalankan ini, saya melihat

  • bahwa polyfill komponen web sedang dimuat dari server web
  • pesan "javascript sedang dieksekusi" di konsol

Apa yang tidak saya lihat?

  • bahwa komponen polymer.html sedang dimuat dari server web
  • pesan "komponen web sudah siap" di konsol

Ini membawa saya pada kesimpulan bahwa acara WebComponentsReady tidak diaktifkan (mungkin karena impor HTML tidak berfungsi?). Juga,
window.WebComponents berisi { flags: { log: {} } } -- indikator ready tidak ada.

Saya juga mencoba beberapa ejekan dan polyfilling:

  window.Object = Object;
  window.Math = Math;
  require('document-register-element/pony')(window);

tapi itu sepertinya tidak mengubah apa pun.

Sekarang, saya bertanya-tanya :-) Apakah ini seharusnya berfungsi sama sekali? Jika demikian, mengapa itu tidak berhasil untuk saya? Jika tidak, apa yang hilang/diperlukan untuk membuatnya berfungsi?

Terima kasih atas wawasan apa pun!

Moin

Saya bahkan mencobanya dengan hasil yang lebih sedikit dan saya menyerah untuk menunggu apa yang akan menjadi hasil diskusi ini di sini.

https://github.com/sebs/noframework/blob/master/test/configurator.js

bukan solusi hanya upaya gagal lainnya. Kebingungan yang sama btw. Kesimpulan yang sama juga

Elemen kustom polyfilling di jsdom terbukti sangat menantang. Adakah yang bisa membuat daftar tantangan untuk mengimplementasikannya di jsdom? Mencoba menilai tingkat upaya untuk memasukkannya.

Hambatan mendasar adalah bahwa jsdom berbagi konstruktor dan prototipe mereka .

Hal ini membuat pada dasarnya tidak mungkin untuk mengimplementasikan registri elemen kustom per jendela, karena konstruktor HTMLElement digunakan bersama di antara semua jendela. Jadi ketika Anda melakukan panggilan super() di konstruktor elemen kustom Anda, konstruktor HTMLElement yang sekarang berjalan tidak tahu jendela apa yang harus dicari. Ini menyebalkan.

Saya tidak yakin apakah ada solusi perantara yang bagus. Senjata besarnya adalah memindahkan jsdom ke arsitektur yang memungkinkan konstruktor/prototipe yang tidak dibagikan. Kita bisa melakukan ini dalam beberapa cara, semua dengan pengorbanan yang berbeda. Mungkin kami ingin membuka masalah khusus untuk mendiskusikannya dengan tim dan komunitas, tetapi untuk saat ini izinkan saya membuat daftar yang muncul di benak saya:

  • Gunakan [WebIDL2JSFactory] untuk semua yang ada di jsdom, atau setidaknya HTMLElement dan semua turunannya. Saya tidak yakin apakah [WebIDL2JSFactory] bahkan berfungsi dengan baik dengan warisan, tetapi itu bisa dibuat berfungsi. Alternatif ini menyebabkan setiap orang membayar biaya konstruktor/prototipe tambahan, tetapi mungkin itu lebih baik daripada menjadikan elemen khusus sebagai fitur keikutsertaan.
  • Miliki opsi di mana jsdom menjalankan semua modul definisi kelas di dalam kotak pasir vm . Misalnya memiliki beberapa langkah pembuatan yang menggabungkan semua API web di jsdom, lalu ketika Anda membuat jendela baru, kami melakukan vm.runScript() dengan bundel itu di dalam global sandbox baru. Ini mungkin memungkinkan kita untuk menyingkirkan [WebIDL2JSFactory] .

Saya kira solusi lain adalah mengimplementasikan elemen khusus dengan peringatan raksasa bahwa registri elemen khusus bersifat global per proses Node.js? Itu tampaknya mengerikan.


Setelah rintangan awal itu, sisanya relatif mudah dalam hal mengikuti spesifikasi. Bagian tersulit mungkin akan menerapkan [CEReactions] dan memperbarui semua file IDL kami untuk memilikinya di tempat yang tepat, tetapi itu tidak terlalu sulit.

Saya telah berpikir untuk memiliki versi prototipe yang terpisah juga. Berikut adalah beberapa pemikiran saya.

Saya tidak yakin apakah [WebIDL2JSFactory] bahkan berfungsi dengan baik dengan pewarisan, tetapi itu bisa dibuat berfungsi.

Tidak, dan saya tidak yakin bagaimana tepatnya membuatnya bekerja. Solusi kedua jauh lebih mudah menurut saya.

Miliki opsi di mana jsdom menjalankan semua modul definisi kelas di dalam kotak pasir vm .

Ini adalah apa yang saya lebih suka. Masalah utama adalah meneruskan kelas impl ke dalam kotak pasir vm selama inisialisasi, meskipun itu dapat dilakukan dengan meletakkan segala sesuatu dari konteks luar ke dalam satu properti global, dan delete properti global itu setelah selesai . Itu juga akan memungkinkan penerapan [NamedConstructor] dengan benar dan beberapa atribut tambahan lainnya, dan bahkan mungkin menghasilkan snapshot startup V8 untuk lingkungan jsdom jika seseorang cukup berani.

Seluruh bisnis [WebIDL2JSFactory] awalnya adalah peretasan, dan saya ingin menyingkirkannya sesegera mungkin.

Komentar +1 tidak membantu untuk mengembangkan fitur ini, jadi saya menghapus setidaknya satu komentar terbaru.

Hai, saya tidak menyadari @TimothyGu sedang mengerjakan ini.
Saya sebenarnya memiliki pendaftaran & pembuatan elemen khusus yang berfungsi di
https://github.com/mraerino/jsdom/tree/custom-elements-spec

Saya mencoba untuk menjadi seminimal mungkin invasif dan juga untuk tetap sedekat mungkin dengan spesifikasi.
Tes platform web Custom Element Registry lulus.

Saat meretas ini tadi malam saya menemukan solusi yang berfungsi tanpa memodifikasi webIdl2JS.
Lihat di sini: https://github.com/mraerino/jsdom/commit/592ad1236e9ca8f63f789d48e1887003305bc618

@TimothyGu apakah Anda bersedia menggabungkan kekuatan yang satu ini?

Hanya beberapa pembaruan di sini:
Saya cukup yakin tentang implementasi spesifikasi saya, tetapi saat ini saya terjebak karena atribut IDL yang diperluas [HTMLConstructor] . Itu sebabnya saya membuka https://github.com/jsdom/webidl2js/issues/87

Sementara itu, saya akan mengimplementasikan algoritma [HTMLConstructor] menggunakan atribut [Constructor] untuk dapat dengan mudah beralih nanti. (Saya awalnya menerapkannya dengan memasukkan kelas HTMLElement tiruan ke window , tetapi ini sepertinya tidak benar.)

Ya, seperti yang tercantum dalam https://github.com/tmpvar/jsdom/issues/1030#issuecomment -333994158 , mengimplementasikan HTMLConstructor dengan benar akan memerlukan perubahan mendasar pada arsitektur jsdom.

Apakah Anda memiliki informasi tentang berapa banyak pengujian platform web yang lulus versi Anda?

Hanya yang customElementRegistry untuk saat ini, dan saya bisa saja salah tentang kemajuan saya.

Sunting: Ok, setelah membaca ulang komentar Anda, saya mengerti maksud Anda. Saya akan mencobanya dengan implementasi saya, tetapi @TimothyGu tampaknya juga sedang mengerjakan pemisahan.

Saya menggunakan Polimer jadi saya :+1: pada fitur permintaan ini

@ dman777 @mraerino Sama untuk pengembang slim.js. Slim menggunakan API komponen web asli dan tidak dapat mewarisi HTMLElement tanpa peretasan di jsdom.

Tiga tahun telah berlalu sejak masalah ini dibuka. Adakah yang bisa mengatakan kapan kira-kira jsdom akan mendukung elemen khusus?

TL;DR

Saya bekerja selama 2 minggu terakhir untuk mengevaluasi kelayakan untuk menambahkan dukungan untuk elemen khusus di jsdom. Berikut hasil investigasinya.

Anda dapat menemukan implementasi elemen kustom yang sesuai dengan spesifikasi di sini: https://github.com/jsdom/jsdom/compare/master...pmdartus :custom-elements?expand=1. Masih ada beberapa tepi kasar di sana-sini, tetapi setidaknya sebagian besar lulus uji WPT . Tes gagal yang tersisa adalah masalah JSDOM yang diketahui atau masalah kecil yang dapat ditangani saat kami akan menangani implementasi aktual di jsdom.

Sekarang inilah kabar baiknya, sekarang Shadow DOM didukung secara asli, dengan cabang elemen kustom dan pengamat mutasi, saya dapat memuat dan merender versi terbaru dari contoh aplikasi hello world Polymer 3 di jsdom . Dalam statusnya saat ini, cabang tidak dapat memuat aplikasi Stensil (mode pengembangan Stensil memerlukan beberapa fitur yang tidak didukung seperti module , dan mode prod muncul karena alasan yang tidak diketahui).

Rencana aksi

Berikut adalah daftar perubahan yang perlu terjadi terlebih dahulu, mulai menangani implementasi spesifikasi elemen kustom yang sebenarnya. Setiap item dalam daftar adalah independen dan dapat ditangani secara paralel.

Dukungan untuk atribut tambahan IDL [CEReactions]

Salah satu inti yang secara fungsional hilang di jsdom untuk menambahkan dukungan untuk elemen khusus adalah atribut [CEReactions] . Saya sebagian dapat mengatasi masalah ini dengan menambal properti prototipe yang tepat. Pendekatan ini berfungsi selama tumpukan reaksi elemen khusus bersifat global dan bukan per unit konteks penelusuran asal serupa yang terkait karena semua prototipe antarmuka dibagikan.

Pendekatan ini memiliki beberapa kekurangan karena beberapa antarmuka memiliki atribut [CEReactions] yang terkait dengan properti yang diindeks ( HTMLOptionsCollection , DOMStringMap ). Secara internal, jsdom menggunakan Proksi untuk melacak mutasi ke properti tersebut. Penambalan prototipe antarmuka tidak berfungsi dalam kasus ini. Pendekatan lain, untuk mengatasi masalah ini adalah dengan menambal implementasi alih-alih antarmuka (tidak diimplementasikan).

Saya tidak cukup akrab dengan internal webidl2js, tetapi kita harus menjelajahi menambahkan kait global untuk [CEReactions] ?

Perubahan:

Dukungan untuk atribut tambahan IDL [HTMLConstructor]

Seperti yang dijelaskan @domenic di atas , menambahkan dukungan untuk [HTMLConstructor] adalah salah satu pemblokir utama di sini.

Saya dapat mengatasi masalah ini di sini dengan menambal konstruktor antarmuka untuk setiap konteks penelusuran. Konstruktor antarmuka akan dapat mengakses jendela kanan dan objek dokumen sambil menjaga prototipe bersama. Pendekatan ini juga menghindari overhead kinerja untuk mengevaluasi kembali prototipe antarmuka untuk setiap konteks penelusuran baru.

Saya tidak yakin apakah ini pendekatan terbaik di sini, tetapi ini sesuai dengan persyaratan tanpa memperkenalkan overhead kinerja tambahan.

Perubahan:

Jadikan spesifikasi algoritme penguraian make fragmen sesuai (#2522)

Seperti yang dibahas di sini , implementasi algo penguraian fragmen HTML yang digunakan dalam Element.innerHTML dan Element.outerHTML salah. Algo parsing perlu di-refactored, agar callback reaksi elemen kustom dipanggil dengan benar.

Perubahan:

Tingkatkan pencarian antarmuka untuk membuat elemen algo

Salah satu masalah yang dengan cepat saya temukan, adalah pengenalan dependensi melingkar baru saat menambahkan dukungan untuk pembuatan elemen kustom. Baik CustomElementRegistry dan algoritma create elemen membutuhkan akses ke antarmuka Element, menciptakan mimpi buruk dependensi melingkar.

Pendekatan yang diambil di cabang adalah untuk membuat InterfaceCache , yang akan memungkinkan pencarian antarmuka oleh namespace elemen dan nama tetapi juga dengan nama antarmuka. Modul antarmuka dievaluasi dan di-cache dengan malas setelah dievaluasi. Pendekatan ini menghilangkan ketergantungan melingkar karena antarmuka tidak lagi diperlukan di tingkat atas.

Ini adalah salah satu pendekatan untuk menyelesaikan masalah lama di jsdom, salah satu masalah ini dengan pendekatan ini adalah bahwa hal itu mungkin akan merusak versi webpacked/browser dari jsdom (tidak diuji).

Perubahan:

~Perbaiki Element.isConnected untuk mendukung Shadow DOM (https://github.com/jsdom/jsdom/pull/2244)~

Ini adalah masalah yang muncul dengan pengenalan DOM bayangan , isConnected mengembalikan false jika elemen tersebut adalah bagian dari pohon bayangan. Tes WPT baru perlu ditambahkan di sini, karena tidak ada tes yang memeriksa perilaku ini.

Perubahan:

Perbaiki dokumen simpul HTMLTemplateElement.templateContents (#2426)

Konten template seperti yang didefinisikan dalam spesifikasi memiliki dokumen simpul yang berbeda dari HTMLTemplateElement itu sendiri. jsdom tidak mengimplementasikan perilaku ini hari ini dan HTMLTemplateElement dan konten templatnya berbagi hal yang sama
simpul dokumen.

Perubahan:

  • HTMLTemplateElement-impl.js
  • htmltodom.js . Perubahan ini juga memiliki beberapa efek hilir pada parser. Jika elemen konteks adalah HTMLTemplateElement, algoritma penguraian fragmen HTML harus mengambil simpul dokumen dari konten template dan bukan dari elemen itu sendiri.

Tambahkan langkah- langkah adopsi yang tidak ada ke HTMLTemplateElement (#2426)

HTMLTemplateElement perlu menjalankan beberapa langkah spesifik saat diadopsi ke dokumen lain. Sejauh yang saya tahu, antarmuka tanah memiliki langkah adopsi khusus. Implementasi algoritma node adopsi juga perlu diperbarui untuk menjalankan langkah adopsi ini.

Perubahan:

Tambahkan dukungan untuk pencarian isValue di parse5 serializer

Fragmen HTML serialisasi juga, ketika membuat serial Elemen mencari nilai is yang terkait dengan elemen dan mencerminkannya sebagai atribut dalam konten serial. Akan menarik untuk menambahkan kait lain di adaptor pohon parse5, yang akan mencari nilai is yang terkait dengan elemen getIsValue(element: Element): void | string .

Pendekatan alternatif (tidak diterapkan) adalah menambahkan perubahan perilaku dari kait getAttrList saat ini untuk mengembalikan nilai is ke daftar atribut, jika elemen memiliki nilai is yang terkait.

Pertunjukan

Sebelum melakukan optimasi kinerja, saya juga ingin memeriksa kinerja perubahan di cabang. Penambahan elemen khusus menambahkan overhead kinerja 10% dibandingkan dengan hasil saat ini pada master untuk tolok ukur mutasi pohon. Namun pembuatan lingkungan JSDOM baru sekarang 3x hingga 6x lebih lambat dibandingkan dengan master, itu akan membutuhkan penyelidikan lebih dalam untuk mengidentifikasi akar masalahnya.

Lebih detail: di sini

@pmdartus ini sangat menjanjikan, kerja bagus! Saya telah menggunakan jsdom-wc cabang hack saya, karena tidak ada opsi yang lebih baik. Saya melihat beberapa perilaku aneh dan berharap untuk menukar cabang Anda, tetapi saya mengalami masalah.

Saya mendaftarkan elemen khusus seperti:

class Component extends HTMLElement {

}

customElements.define('custom-component', Component);

Tetapi jika saya melakukannya:

const el = assign(this.fixture, {
  innerHTML: `
    <custom-component></custom-component>
  `,
});

Saya langsung mendapatkan: Error: Uncaught [TypeError: Illegal constructor] .

Ada pemikiran tentang ini?

Cuplikan kode berikut berjalan dengan benar di cabang custom-elements di fork saya: https://github.com/pmdartus/jsdom/tree/custom-elements

const { JSDOM } = require("jsdom");

const dom = new JSDOM(`
<body>
  <div id="container"></div>
  <script>
    class Component extends HTMLElement {
        connectedCallback() {
            this.attachShadow({ mode: "open" });
            this.shadowRoot.innerHTML = "<p>Hello world</p>";
        }
    }
    customElements.define('custom-component', Component);

    const container = document.querySelector("#container");

    Object.assign(container, {
        innerHTML: "<custom-component></custom-component>"
    })

    console.log(container.innerHTML); // <custom-component></custom-component>
    console.log(container.firstChild.shadowRoot.innerHTML); // <p>Hello world</p>
  </script>
</body>
`, { 
    runScripts: "dangerously" 
});

Konstruktor ilegal mungkin dilempar oleh konstruktor HTMLElement asli, perubahan yang dibuat pada cabang harus menambal konstruktor untuk setiap objek jendela baru. @tbranyen Apakah Anda memiliki contoh reproduksi lengkap sehingga saya dapat mencobanya secara lokal?

Hai @pmdartus Saya belum terlalu yakin apa yang menyebabkan masalah saya, tetapi saya menulis beberapa kode terisolasi langsung ke cabang Anda yang berfungsi dengan baik:

const { JSDOM } = require('.');
const window = (new JSDOM()).window;
const { HTMLElement, customElements, document } = window;

class CustomElement extends HTMLElement {
  constructor() {
    super();

    console.log('constructed');
  }

  connectedCallback() {
    console.log('connected');
  }
}

customElements.define('custom-element', CustomElement);
document.body.appendChild(new CustomElement());
//constructed
//connected

{
  const window = (new JSDOM()).window;
  const { HTMLElement, customElements, document } = window;

  class CustomElement extends HTMLElement {
    constructor() {
      super();

      console.log('Constructed');
    }

    connectedCallback() {
      console.log('Connected');
    }
  }

  customElements.define('custom-element', CustomElement);
  document.body.appendChild(new CustomElement());
  //constructed
  //connected
}

Ini secara efektif apa yang dilakukan sistem pengujian saya, tetapi rusak. Jadi itu mungkin sesuatu di pihak saya.

Sunting:

Ah oke saya pikir saya mempersempit di mana masalah kemungkinan besar terjadi. Saya harus berpegang pada konstruktor HTMLElement awal yang dibuat. Jika saya menyesuaikan kode di atas untuk menggunakan kembali konstruktor:

  // Inside the block, second component, reuse the HTMLElement.
  const { customElements, document } = window;

Ini akan menghasilkan yang berikut:

connected
/home/tbranyen/git/pmdartus/jsdom/lib/jsdom/living/helpers/create-element.js:643
        throw new TypeError("Illegal constructor");

Sunting 2:

Menemukannya:

  // Don't reuse the previously defined Element...
  global.HTMLElement = global.HTMLElement || jsdom.window.HTMLElement;

Memperhatikan utas ini berusia 4 tahun, apakah komponen web didukung atau direncanakan?

Akan menyenangkan untuk memiliki komponen web dalam hal ini, tetapi sebagai alternatif jika ada yang ingin tahu.... headless chrome sekarang dapat digunakan di node untuk merender/membangun file html sting.

Memperhatikan utas ini berusia 4 tahun, apakah komponen web didukung atau direncanakan?

Ini sedang dalam proses karena spesifikasi diimplementasikan sepotong demi sepotong.

Polyfill di: https://github.com/WebReflection/document-register-element Bekerja seperti pesona! Terima kasih saya yang paling tulus kepada penulis!

Bagi mereka yang berjuang dengan masalah yang sama, lakukan saja:

npm install -D document-register-element

Dalam konfigurasi lelucon Anda, atur file pengaturan yang akan dijalankan sebelum semua pengujian Anda:

{ "setupFilesAfterEnv": [ "./tests/setup.js" ] }

Dan akhirnya, di dalam file itu ('tests/setup.js'):

import 'document-register-element'

Setelah melakukan ini, mendaftarkan dan membuat elemen kustom di jsdom melalui document.createElement('custom-component') bekerja dengan sempurna! Namun, fragmen tampaknya tidak berfungsi. (Omong-omong, saya tidak menggunakan shadow dom).

@tebanep seperti yang Anda sebutkan bahwa polyfill tidak cocok untuk sebagian besar pekerjaan Komponen Web, jika tidak mendukung Shadow DOM maka itu bukan perbandingan dengan apa yang dicapai.

@tebanep Terima kasih. Karena saya tidak membutuhkan shadow dom, ini adalah info yang bagus

Adakah harapan bahwa ini akan dilaksanakan? Saat ini kami menggunakan jsdom-wc dengan banyak bug, tetapi belum memiliki solusi yang lebih baik. Harapan dan doa saya tentang topik ini.

@dknight Saya tahu jsdom-wc cukup banyak diretas untuk membuatnya agak berfungsi. Saya menerbitkan modul dengan kompatibilitas yang jauh lebih baik di bawah lingkup npm pribadi saya. Anda dapat menginstalnya dengan:

npm install @tbranyen/[email protected] --save-dev

Saya menggunakan ini sekarang untuk semua kebutuhan komponen web JSDOM saya hingga stabil.

@tbranyen Apakah Anda membatalkan publikasi garpu Anda? Saya tidak dapat menemukannya di npm.

@KingHenne dangit, sepertinya itu berakhir di registri "perusahaan" kami. Saya baru saja menerbitkan ke npm publik. Maaf tentang itu!

Jangan @ saya, tapi bukankah seharusnya kita hanya menguji kode web ui di browser nyata misalnya dengan dalang. Masalah dukungan Shadow DOM/Elemen Kustom hilang kemudian.

Jangan posting komentar jika Anda tidak ingin menjadi @'d @Georgegriff. Itu strategi yang valid, tapi lambat dan bermasalah dengan cara lain karena Anda secara efektif melakukan IPC, ya bahkan dengan dalang. Ketika browser mati, tidak jelas mengapa dalam banyak kasus. Coba saja dan debug masalah dalang dengan bercanda untuk mengetahui mengapa itu tidak selalu merupakan ide terbaik.

Secara pribadi saya lebih suka terus menguji sinkron dan di utas yang sama. Tidak ada alasan mengapa implementasi spesifikasi yang terisolasi tidak boleh menjadi runtime yang wajar untuk menguji komponen. JSDOM secara efektif merupakan browser pada saat ini, hanya saja tidak stabil seperti tiga besar.

Polyfill di: https://github.com/WebReflection/document-register-element Bekerja seperti pesona! Terima kasih saya yang paling tulus kepada penulis!

Bagi mereka yang berjuang dengan masalah yang sama, lakukan saja:

npm install -D document-register-element

Dalam konfigurasi lelucon Anda, atur file pengaturan yang akan dijalankan sebelum semua pengujian Anda:

{ "setupFilesAfterEnv": [ "./tests/setup.js" ] }

Dan akhirnya, di dalam file itu ('tests/setup.js'):

import 'document-register-element'

Setelah melakukan ini, mendaftarkan dan membuat elemen kustom di jsdom melalui document.createElement('custom-component') bekerja dengan sempurna! Namun, fragmen tampaknya tidak berfungsi. (Omong-omong, saya tidak menggunakan shadow dom).

Ini berfungsi dengan baik untuk saya tetapi connectedCallback tidak pernah dipanggil, ada ide?

@FaBeyyy sama untuk saya :(

@FaBeyyy @majo44 Anda harus menambahkan komponen Anda ke dokumen yaitu. document.body.appendChild(...) untuk connectedCallback untuk dipecat. Dengan spesifikasi itu dipanggil ketika komponen dilampirkan ke Dom.

JSDOM secara efektif merupakan browser pada saat ini, hanya saja tidak stabil seperti tiga besar.

Pada titik ini, ini lebih seperti dua besar, karena Microsoft membuang milik mereka, yang telah bersama mereka selama Windows.

@FaBeyyy @majo44 Anda harus menambahkan komponen Anda ke dokumen yaitu. document.body.appendChild(...) untuk connectedCallback untuk dipecat. Dengan spesifikasi itu dipanggil ketika komponen dilampirkan ke Dom.

terima kasih kapten jelas tapi itu tentu saja bukan masalah di sini. Jika saya tidak tahu bagaimana siklus hidup komponen bekerja, saya mungkin tidak akan mencoba menulis tes . Akan membuat showcase repo nanti ketika saya menemukan waktu.

@FaBeyyy
Jadi saya menemukan pengaturan yang sesuai untuk saya. Saya harus menambahkan polyfill untuk MutationObserver. Saya menggunakan JSDOM untuk menguji lumba-lumba, dengan Jest, dan pengaturan kerjanya adalah:

// package.json
{  ...
  "jest": {
    "transform": {
      "^.+\\.(mjs|jsx|js)$": "babel-jest"
    },
    "setupFiles": [
      "<rootDir>/node_modules/babel-polyfill/dist/polyfill.js",
      "<rootDir>/node_modules/mutationobserver-shim/dist/mutationobserver.min.js",
      "<rootDir>/node_modules/document-register-element/build/document-register-element.node.js"
    ]
  }
... 
}
//.bablerc
{
    "presets": [
        ["@babel/preset-env", { "modules": "commonjs"}]
    ]
}

@FaBeyyy
Jadi saya menemukan pengaturan yang sesuai untuk saya. Saya harus menambahkan polyfill untuk MutationObserver. Saya menggunakan JSDOM untuk menguji lumba-lumba, dengan Jest, dan pengaturan kerjanya adalah:

// package.json
{  ...
  "jest": {
    "transform": {
      "^.+\\.(mjs|jsx|js)$": "babel-jest"
    },
    "setupFiles": [
      "<rootDir>/node_modules/babel-polyfill/dist/polyfill.js",
      "<rootDir>/node_modules/mutationobserver-shim/dist/mutationobserver.min.js",
      "<rootDir>/node_modules/document-register-element/build/document-register-element.node.js"
    ]
  }
... 
}

//.bablerc { "presets": [ ["@babel/preset-env", { "modules": "commonjs"}] ] }

Terima kasih banyak!

@majo44 ini tidak diperlukan dengan jsdom terbaru. Saat bekerja dengan Jest (yang menggunakan jsdom v11), Anda bisa menggunakan lingkungan yang diperbarui: https://www.npmjs.com/package/jest-environment-jsdom-fourteen

@mgibas terima kasih, dengan jest-environment-jsdom-fourteen ini juga berfungsi dengan baik dan polyfill pengamat mutasi tidak diperlukan (tetapi versi 0.1.0, paket komit tunggal :))

Apakah ada perincian API komponen web mana yang saat ini didukung oleh JSDOM? Sepertinya shadow DOM didukung, tetapi bukan elemen khusus (setidaknya di cabang/repo rilis)?

npm install @tbranyen/[email protected] --save-dev

@tbranyen apakah Anda memiliki kode sumber untuk garpu Anda tersedia di suatu tempat? Akan penasaran untuk melihat perbedaannya

Saya menggunakan jest-environment-jsdom-fifteen seperti yang disarankan @majo44 , dan elemen babel-polyfill dan dokumen-register (lihat jawaban @mgibas ). Tetapi saya masih mendapatkan kesalahan ketika saya mencoba mengambil kembali shadow dom komponen web saya untuk pengujian.

el.shadowRoot adalah nol dengan:

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] > *');
})

Adakah ide untuk solusi? FYI, itu sudah diuji dengan Karma, Mocha, Chai & Jasmine.

Tidak ada yang istimewa di komponen saya:

customElements.define(
  'my-component',
  class extends HTMLElement {
    constructor() {
      super();

      const shadowRoot = this.attachShadow({ mode: 'open' });
      ...
  }
})

Sunting

Saya melakukan beberapa debugging dengan jsdom 15.1.1 untuk lebih memahami masalah saya.
Tetap saja, saya tidak mengerti mengapa itu nol di sini ...

Jadi, Element.shadowRoot diimplementasikan sejak 88e72ef
https://github.com/jsdom/jsdom/blob/1951a19d8d40bc196cfda62a8dafa76ddda6a0d2/lib/jsdom/living/nodes/Element-impl.js#L388 -L415

Setelah document.createElement, this._shadowDom ok di https://github.com/jsdom/jsdom/blob/15.1.1/lib/jsdom/living/nodes/Element-impl.js#L403. Dan setiap elemen dalam shadow dom dibuat (Konstruktor elemen disebut dengan nilai yang tepat).

Tetapi ketika saya menelepon el.shadowDom segera setelah document.body.appendChild(el) (https://github.com/jsdom/jsdom/blob/15.1.1/lib/jsdom/living/nodes/Element-impl .js#L408), this. _shadowRoot adalah nol!

Hal yang sama setelah

 await customElements.whenDefined(tag);
 await new Promise(resolve => requestAnimationFrame(() => resolve()));

Atau bahkan jika saya menggunakan yang berikut ini alih-alih dokumen.

document.body.innerHTML = `
  <my-component id="fixture"></my-component>
`:

Untuk reproduksi, lihat:
https://github.com/noelmace/devcards/tree/jest

@nminhnguyen Saya kira Anda dapat menemukan kode sumber garpu yang dibuat oleh @tbranyan di sini https://github.com/tbranyen/jsdom/tree/initial-custom-elements-impl

Saya mencoba menguji komponen web yang dibuat dengan lit-html dan lit-element dan saya melihat perbedaan ini saat membuat elemen.

const myElem = new MyElem();

document.body.appendChild(myElem);
await myElem.updateComplete;

console.log(myElem.shadowRoot) // exists and has the rendered markup

dan ketika saya menggunakan document.createElement

const myElem = document.createElement('my-elem');

document.body.appendChild(myElem);
await myElem.updateComplete;

console.log(myElem.shadowRoot) // null

Untuk konfigurasi jest saya hanya menggunakan satu polyfill yaitu : setupFiles: ['document-register-element']

Tampaknya metode render di myElem tidak pernah dipanggil. Debugging sedikit lebih jauh Saya telah menemukan bahwa metode initialize yang ada di lit-element tidak pernah dipanggil.
Jadi contoh ke-2 akan berhasil jika saya melakukannya

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

Saya telah membuat DOM alternatif yang mendukung komponen web. Saya pertama kali mencoba membuat PR, tetapi cara kerja JSDOM membuat saya sulit untuk menyelesaikan kebutuhan saya di sana. Anda bebas menggunakannya atau melihat kodenya.

DOM:
https://www.npmjs.com/package/happy-dom

Lingkungan bercanda:
https://www.npmjs.com/package/jest-environment-happy-dom

Tampak menakjubkan. Terima kasih.

Pada Senin, 7 Oktober 2019, 01:08 capricorn86 [email protected] menulis:

Saya telah membuat DOM alternatif yang mendukung komponen web. saya pertama
mencoba membuat PR, tetapi cara kerja JSDOM membuat saya sulit untuk menyelesaikannya
kebutuhan di sana. Anda bebas menggunakannya dan/atau melihat kodenya.

DOM:
https://www.npmjs.com/package/happy-dom

Lingkungan bercanda:
https://www.npmjs.com/package/jest-environment-happy-dom


Anda menerima ini karena Anda berlangganan utas ini.
Balas email ini secara langsung, lihat di GitHub
https://github.com/jsdom/jsdom/issues/1030?email_source=notifications&email_token=ACQ5ZD5QUEITPND4SXWOHW3QNILSRA5CNFSM4A4G5SF2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW2ZEADOOOR5ZWZJKTOOOR5NMVXHJKTissue
atau matikan utasnya
https://github.com/notifications/unsubscribe-auth/ACQ5ZDYU465DXI4KHBQH4KTQNILSRANCNFSM4A4G5SFQ
.

@capricorn86
Pekerjaan Anda membuat lingkungan Pengujian saya sederhana, terima kasih!
https://github.com/EasyWebApp/WebCell/tree/v2/MobX

@capricorn86
Pekerjaan Anda membuat lingkungan Pengujian saya sederhana, terima kasih!
https://github.com/EasyWebApp/WebCell/tree/v2/MobX

Terima kasih @TechQuery!

Tampak menakjubkan. Terima kasih.

Pada Senin, 7 Okt 2019, 01:08 capricorn86 @ . * > menulis: Saya telah membuat DOM alternatif yang mendukung komponen web. Saya pertama kali mencoba membuat PR, tetapi cara kerja JSDOM membuat saya sulit untuk menyelesaikan kebutuhan saya di sana. Anda bebas menggunakannya dan/atau melihat kodenya. DOM: https://www.npmjs.com/package/happy-dom Lingkungan lelucon: https://www.npmjs.com/package/jest-environment-happy-dom — Anda menerima ini karena Anda berlangganan ini benang. Balas email ini secara langsung, melihatnya di GitHub <# 1030? Email_source = pemberitahuan & email_token = ACQ5ZD5QUEITPND4SXWOHW3QNILSRA5CNFSM4A4G5SF2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEAOO5ZA # issuecomment-538.767.076>, atau mematikan benang https://github.com/notifications/unsubscribe-auth/ACQ5ZDYU465DXI4KHBQH4KTQNILSRANCNFSM4A4G5SFQ .

Terima kasih @motss!

Apakah ada perincian API komponen web mana yang saat ini didukung oleh JSDOM? Sepertinya shadow DOM didukung, tetapi bukan elemen khusus (setidaknya di cabang/repo rilis)?

Saya juga tertarik dengan ini :)

Apakah halaman ini membantu?
0 / 5 - 0 peringkat

Masalah terkait

eszthoff picture eszthoff  ·  3Komentar

Progyan1997 picture Progyan1997  ·  3Komentar

tolmasky picture tolmasky  ·  4Komentar

domenic picture domenic  ·  3Komentar

lehni picture lehni  ·  4Komentar