@@ -3,13 +3,57 @@ import { setupPuppeteer } from './e2eUtils'
33
44const { page, click, text } = setupPuppeteer ( )
55
6+ beforeEach ( async ( ) => {
7+ await page ( ) . addScriptTag ( {
8+ path : path . resolve ( __dirname , '../../dist/vue.global.js' ) ,
9+ } )
10+ } )
11+
12+ async function setContent ( html : string ) {
13+ await page ( ) . setContent ( `<div id="app">${ html } </div>` )
14+ }
15+
616// this must be tested in actual Chrome because jsdom does not support
717// declarative shadow DOM
818test ( 'ssr custom element hydration' , async ( ) => {
9- await page ( ) . goto (
10- `file:// ${ path . resolve ( __dirname , './ssr-custom -element.html' ) } ` ,
19+ await setContent (
20+ `<my-element><template shadowrootmode="open"><button>1</button></template></my-element><my -element-async><template shadowrootmode="open"><button>1</button></template></my-element-async> ` ,
1121 )
1222
23+ await page ( ) . evaluate ( ( ) => {
24+ const {
25+ h,
26+ ref,
27+ defineSSRCustomElement,
28+ defineAsyncComponent,
29+ onMounted,
30+ useHost,
31+ } = ( window as any ) . Vue
32+
33+ const def = {
34+ setup ( ) {
35+ const count = ref ( 1 )
36+ const el = useHost ( )
37+ onMounted ( ( ) => ( el . style . border = '1px solid red' ) )
38+
39+ return ( ) => h ( 'button' , { onClick : ( ) => count . value ++ } , count . value )
40+ } ,
41+ }
42+
43+ customElements . define ( 'my-element' , defineSSRCustomElement ( def ) )
44+ customElements . define (
45+ 'my-element-async' ,
46+ defineSSRCustomElement (
47+ defineAsyncComponent (
48+ ( ) =>
49+ new Promise ( r => {
50+ ; ( window as any ) . resolve = ( ) => r ( def )
51+ } ) ,
52+ ) ,
53+ ) ,
54+ )
55+ } )
56+
1357 function getColor ( ) {
1458 return page ( ) . evaluate ( ( ) => {
1559 return [
@@ -33,3 +77,55 @@ test('ssr custom element hydration', async () => {
3377 await assertInteraction ( 'my-element' )
3478 await assertInteraction ( 'my-element-async' )
3579} )
80+
81+ // #11641
82+ test ( 'pass key to custom element' , async ( ) => {
83+ const messages : string [ ] = [ ]
84+ page ( ) . on ( 'console' , e => messages . push ( e . text ( ) ) )
85+
86+ await setContent (
87+ `<!--[--><my-element str="1"><template shadowrootmode="open"><div>1</div></template></my-element><!--]-->` ,
88+ )
89+ await page ( ) . evaluate ( ( ) => {
90+ const {
91+ h,
92+ ref,
93+ defineSSRCustomElement,
94+ onBeforeUnmount,
95+ onMounted,
96+ createSSRApp,
97+ renderList,
98+ } = ( window as any ) . Vue
99+
100+ const MyElement = defineSSRCustomElement ( {
101+ props : {
102+ str : String ,
103+ } ,
104+ setup ( props : any ) {
105+ onMounted ( ( ) => {
106+ console . log ( 'child mounted' )
107+ } )
108+ onBeforeUnmount ( ( ) => {
109+ console . log ( 'child unmount' )
110+ } )
111+ return ( ) => h ( 'div' , props . str )
112+ } ,
113+ } )
114+ customElements . define ( 'my-element' , MyElement )
115+
116+ createSSRApp ( {
117+ setup ( ) {
118+ const arr = ref ( [ '1' ] )
119+ // pass key to custom element
120+ return ( ) =>
121+ renderList ( arr . value , ( i : string ) =>
122+ h ( 'my-element' , { key : i , str : i } , null ) ,
123+ )
124+ } ,
125+ } ) . mount ( '#app' )
126+ } )
127+
128+ expect ( messages . includes ( 'child mounted' ) ) . toBe ( true )
129+ expect ( messages . includes ( 'child unmount' ) ) . toBe ( false )
130+ expect ( await text ( 'my-element >>> div' ) ) . toBe ( '1' )
131+ } )
0 commit comments