|
|
@@ -3,13 +3,57 @@ import { setupPuppeteer } from './e2eUtils'
|
|
|
|
|
|
const { page, click, text } = setupPuppeteer()
|
|
|
|
|
|
+beforeEach(async () => {
|
|
|
+ await page().addScriptTag({
|
|
|
+ path: path.resolve(__dirname, '../../dist/vue.global.js'),
|
|
|
+ })
|
|
|
+})
|
|
|
+
|
|
|
+async function setContent(html: string) {
|
|
|
+ await page().setContent(`<div id="app">${html}</div>`)
|
|
|
+}
|
|
|
+
|
|
|
// this must be tested in actual Chrome because jsdom does not support
|
|
|
// declarative shadow DOM
|
|
|
test('ssr custom element hydration', async () => {
|
|
|
- await page().goto(
|
|
|
- `file://${path.resolve(__dirname, './ssr-custom-element.html')}`,
|
|
|
+ await setContent(
|
|
|
+ `<my-element><template shadowrootmode="open"><button>1</button></template></my-element><my-element-async><template shadowrootmode="open"><button>1</button></template></my-element-async>`,
|
|
|
)
|
|
|
|
|
|
+ await page().evaluate(() => {
|
|
|
+ const {
|
|
|
+ h,
|
|
|
+ ref,
|
|
|
+ defineSSRCustomElement,
|
|
|
+ defineAsyncComponent,
|
|
|
+ onMounted,
|
|
|
+ useHost,
|
|
|
+ } = (window as any).Vue
|
|
|
+
|
|
|
+ const def = {
|
|
|
+ setup() {
|
|
|
+ const count = ref(1)
|
|
|
+ const el = useHost()
|
|
|
+ onMounted(() => (el.style.border = '1px solid red'))
|
|
|
+
|
|
|
+ return () => h('button', { onClick: () => count.value++ }, count.value)
|
|
|
+ },
|
|
|
+ }
|
|
|
+
|
|
|
+ customElements.define('my-element', defineSSRCustomElement(def))
|
|
|
+ customElements.define(
|
|
|
+ 'my-element-async',
|
|
|
+ defineSSRCustomElement(
|
|
|
+ defineAsyncComponent(
|
|
|
+ () =>
|
|
|
+ new Promise(r => {
|
|
|
+ ;(window as any).resolve = () => r(def)
|
|
|
+ }),
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ )
|
|
|
+ })
|
|
|
+
|
|
|
function getColor() {
|
|
|
return page().evaluate(() => {
|
|
|
return [
|
|
|
@@ -33,3 +77,55 @@ test('ssr custom element hydration', async () => {
|
|
|
await assertInteraction('my-element')
|
|
|
await assertInteraction('my-element-async')
|
|
|
})
|
|
|
+
|
|
|
+// #11641
|
|
|
+test('pass key to custom element', async () => {
|
|
|
+ const messages: string[] = []
|
|
|
+ page().on('console', e => messages.push(e.text()))
|
|
|
+
|
|
|
+ await setContent(
|
|
|
+ `<!--[--><my-element str="1"><template shadowrootmode="open"><div>1</div></template></my-element><!--]-->`,
|
|
|
+ )
|
|
|
+ await page().evaluate(() => {
|
|
|
+ const {
|
|
|
+ h,
|
|
|
+ ref,
|
|
|
+ defineSSRCustomElement,
|
|
|
+ onBeforeUnmount,
|
|
|
+ onMounted,
|
|
|
+ createSSRApp,
|
|
|
+ renderList,
|
|
|
+ } = (window as any).Vue
|
|
|
+
|
|
|
+ const MyElement = defineSSRCustomElement({
|
|
|
+ props: {
|
|
|
+ str: String,
|
|
|
+ },
|
|
|
+ setup(props: any) {
|
|
|
+ onMounted(() => {
|
|
|
+ console.log('child mounted')
|
|
|
+ })
|
|
|
+ onBeforeUnmount(() => {
|
|
|
+ console.log('child unmount')
|
|
|
+ })
|
|
|
+ return () => h('div', props.str)
|
|
|
+ },
|
|
|
+ })
|
|
|
+ customElements.define('my-element', MyElement)
|
|
|
+
|
|
|
+ createSSRApp({
|
|
|
+ setup() {
|
|
|
+ const arr = ref(['1'])
|
|
|
+ // pass key to custom element
|
|
|
+ return () =>
|
|
|
+ renderList(arr.value, (i: string) =>
|
|
|
+ h('my-element', { key: i, str: i }, null),
|
|
|
+ )
|
|
|
+ },
|
|
|
+ }).mount('#app')
|
|
|
+ })
|
|
|
+
|
|
|
+ expect(messages.includes('child mounted')).toBe(true)
|
|
|
+ expect(messages.includes('child unmount')).toBe(false)
|
|
|
+ expect(await text('my-element >>> div')).toBe('1')
|
|
|
+})
|