@@ -3,13 +3,57 @@ import { setupPuppeteer } from './e2eUtils'
3
3
4
4
const { page, click, text } = setupPuppeteer ( )
5
5
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
+
6
16
// this must be tested in actual Chrome because jsdom does not support
7
17
// declarative shadow DOM
8
18
test ( '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> ` ,
11
21
)
12
22
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
+
13
57
function getColor ( ) {
14
58
return page ( ) . evaluate ( ( ) => {
15
59
return [
@@ -33,3 +77,55 @@ test('ssr custom element hydration', async () => {
33
77
await assertInteraction ( 'my-element' )
34
78
await assertInteraction ( 'my-element-async' )
35
79
} )
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