1
1
import { describe , test , it , expect , vi , afterEach } from "vitest"
2
2
import matchers from "@testing-library/jest-dom/matchers"
3
- import React from "react"
4
3
5
4
import r2wc from "./core"
6
5
7
6
expect . extend ( matchers )
8
7
9
- const mountCheck = vi . fn ( )
8
+ const mount = vi . fn ( ( ) => ( { why : "context" } ) )
10
9
const unmount = vi . fn ( )
11
10
const update = vi . fn ( )
12
- const onUpdated = vi . fn ( )
13
-
14
- const mount = ( el : HTMLElement , reactComponent : any , _props : any ) => {
15
- mountCheck ( )
16
- return {
17
- reactContainer : el ,
18
- component : reactComponent ,
19
- }
20
- }
21
11
22
- function flushPromises ( ) {
12
+ function wait ( ) {
23
13
return new Promise ( ( resolve ) => setImmediate ( resolve ) )
24
14
}
25
15
@@ -28,40 +18,62 @@ describe("core", () => {
28
18
document . body . innerHTML = ""
29
19
} )
30
20
31
- it ( "mounts and unmounts for a functional component" , async ( ) => {
32
- function TestComponent ( ) {
33
- return < div > hello</ div >
34
- }
21
+ it ( "mounts and unmounts in light mode" , async ( ) => {
22
+ const ReactComponent : React . FC = ( ) => < h1 > Hello</ h1 >
35
23
36
- const TestElement = r2wc ( TestComponent , { } , { mount, unmount, update } )
37
- customElements . define ( "test-func-element " , TestElement )
24
+ const WebComponent = r2wc ( ReactComponent , { } , { mount, unmount, update } )
25
+ customElements . define ( "test-light " , WebComponent )
38
26
39
- const testEl = new TestElement ( )
27
+ const element = new WebComponent ( )
40
28
41
- document . body . appendChild ( testEl )
42
- expect ( mountCheck ) . toBeCalledTimes ( 1 )
29
+ document . body . appendChild ( element )
30
+ expect ( mount ) . toBeCalledTimes ( 1 )
43
31
44
- document . body . removeChild ( testEl )
32
+ document . body . removeChild ( element )
45
33
expect ( unmount ) . toBeCalledTimes ( 1 )
34
+ expect ( unmount ) . toBeCalledWith ( { why : "context" } )
46
35
} )
47
36
48
- it ( "mounts and unmounts for a class component" , async ( ) => {
49
- class TestComponent extends React . Component {
50
- render ( ) {
51
- return < div > hello</ div >
52
- }
53
- }
37
+ it ( "mounts and unmounts in open shadow mode" , async ( ) => {
38
+ const ReactComponent : React . FC = ( ) => < h1 > Hello</ h1 >
39
+
40
+ const WebComponent = r2wc (
41
+ ReactComponent ,
42
+ { shadow : "open" } ,
43
+ { mount, unmount, update } ,
44
+ )
45
+ customElements . define ( "test-shadow-open" , WebComponent )
46
+
47
+ const element = new WebComponent ( )
54
48
55
- const TestElement = r2wc ( TestComponent , { } , { mount, unmount, update } )
56
- customElements . define ( "test-element" , TestElement )
49
+ document . body . appendChild ( element )
50
+ expect ( element ) . toHaveProperty ( "shadowRoot" )
51
+ expect ( mount ) . toBeCalledTimes ( 1 )
52
+
53
+ document . body . removeChild ( element )
54
+ expect ( unmount ) . toBeCalledTimes ( 1 )
55
+ expect ( unmount ) . toBeCalledWith ( { why : "context" } )
56
+ } )
57
+
58
+ it ( "mounts and unmounts in closed shadow mode" , async ( ) => {
59
+ const ReactComponent : React . FC = ( ) => < h1 > Hello</ h1 >
60
+
61
+ const WebComponent = r2wc (
62
+ ReactComponent ,
63
+ { shadow : "closed" } ,
64
+ { mount, unmount, update } ,
65
+ )
66
+ customElements . define ( "test-shadow-closed" , WebComponent )
57
67
58
- const testEl = new TestElement ( )
68
+ const element = new WebComponent ( )
59
69
60
- document . body . appendChild ( testEl )
61
- expect ( mountCheck ) . toBeCalledTimes ( 1 )
70
+ document . body . appendChild ( element )
71
+ expect ( element ) . toHaveProperty ( "shadowRoot" )
72
+ expect ( mount ) . toBeCalledTimes ( 1 )
62
73
63
- document . body . removeChild ( testEl )
74
+ document . body . removeChild ( element )
64
75
expect ( unmount ) . toBeCalledTimes ( 1 )
76
+ expect ( unmount ) . toBeCalledWith ( { why : "context" } )
65
77
} )
66
78
67
79
test ( "updated attribute updates the component prop and the HTMLElement property" , async ( ) => {
@@ -72,7 +84,7 @@ describe("core", () => {
72
84
const ButtonElement = r2wc (
73
85
Button ,
74
86
{ props : [ "text" ] } ,
75
- { mount, unmount, update, onUpdated } ,
87
+ { mount, unmount, update } ,
76
88
)
77
89
78
90
customElements . define ( "test-button-element-attribute" , ButtonElement )
@@ -81,20 +93,18 @@ describe("core", () => {
81
93
body . innerHTML =
82
94
"<test-button-element-attribute text='hello'></test-button-element-attribute>"
83
95
84
- const testEl = body . querySelector (
96
+ const element = body . querySelector (
85
97
"test-button-element-attribute" ,
86
98
) as HTMLElement & { text : string }
87
99
88
- testEl . setAttribute ( "text" , "world" )
100
+ element . setAttribute ( "text" , "world" )
89
101
90
- await flushPromises ( )
102
+ await wait ( )
91
103
92
- expect ( onUpdated ) . toBeCalledTimes ( 1 )
93
- expect ( testEl . text ) . toBe ( "world" )
104
+ expect ( element . text ) . toBe ( "world" )
94
105
} )
95
106
96
107
test ( "updated HTMLElement property updates the component prop and the HTMLElement attribute" , async ( ) => {
97
- expect . assertions ( 13 )
98
108
interface Props {
99
109
text : string
100
110
numProp : number
@@ -127,7 +137,7 @@ describe("core", () => {
127
137
funcProp : "function" ,
128
138
} ,
129
139
} ,
130
- { mount, unmount, update, onUpdated } ,
140
+ { mount, unmount, update } ,
131
141
)
132
142
133
143
//@ts -ignore
@@ -147,33 +157,32 @@ describe("core", () => {
147
157
body . innerHTML = `<test-button-element-property text='hello' obj-prop='{"greeting": "hello, world"}' arr-prop='["hello", "world"]' num-prop='240' bool-prop='true' func-prop='globalFn'>
148
158
</test-button-element-property>`
149
159
150
- const testEl = body . querySelector (
160
+ const element = body . querySelector (
151
161
"test-button-element-property" ,
152
162
) as HTMLElement & Props
153
163
154
- await flushPromises ( )
164
+ await wait ( )
155
165
156
- expect ( testEl . text ) . toBe ( "hello" )
157
- expect ( testEl . numProp ) . toBe ( 240 )
158
- expect ( testEl . boolProp ) . toBe ( true )
159
- expect ( testEl . arrProp ) . toEqual ( [ "hello" , "world" ] )
160
- expect ( testEl . objProp ) . toEqual ( { greeting : "hello, world" } )
161
- expect ( testEl . funcProp ) . toBeInstanceOf ( Function )
162
- expect ( testEl . funcProp ( ) ) . toBe ( true )
166
+ expect ( element . text ) . toBe ( "hello" )
167
+ expect ( element . numProp ) . toBe ( 240 )
168
+ expect ( element . boolProp ) . toBe ( true )
169
+ expect ( element . arrProp ) . toEqual ( [ "hello" , "world" ] )
170
+ expect ( element . objProp ) . toEqual ( { greeting : "hello, world" } )
171
+ expect ( element . funcProp ) . toBeInstanceOf ( Function )
172
+ expect ( element . funcProp ( ) ) . toBe ( true )
163
173
164
- testEl . text = "world"
165
- testEl . numProp = 100
166
- testEl . boolProp = false
174
+ element . text = "world"
175
+ element . numProp = 100
176
+ element . boolProp = false
167
177
//@ts -ignore
168
- testEl . funcProp = global . newFunc
178
+ element . funcProp = global . newFunc
169
179
170
- await flushPromises ( )
180
+ await wait ( )
171
181
172
- expect ( onUpdated ) . toBeCalledTimes ( 4 )
173
- expect ( testEl . getAttribute ( "text" ) ) . toBe ( "world" )
174
- expect ( testEl . getAttribute ( "num-prop" ) ) . toBe ( "100" )
175
- expect ( testEl . getAttribute ( "bool-prop" ) ) . toBe ( "false" )
176
- expect ( testEl . getAttribute ( "func-prop" ) ) . toBe ( "newFunc" )
182
+ expect ( element . getAttribute ( "text" ) ) . toBe ( "world" )
183
+ expect ( element . getAttribute ( "num-prop" ) ) . toBe ( "100" )
184
+ expect ( element . getAttribute ( "bool-prop" ) ) . toBe ( "false" )
185
+ expect ( element . getAttribute ( "func-prop" ) ) . toBe ( "newFunc" )
177
186
} )
178
187
179
188
test ( "sets HTML property not defined in props but found on HTML object" , async ( ) => {
@@ -184,25 +193,25 @@ describe("core", () => {
184
193
const ButtonElement = r2wc (
185
194
Button ,
186
195
{ props : [ "text" ] } ,
187
- { mount, unmount, update, onUpdated } ,
196
+ { mount, unmount, update } ,
188
197
)
189
198
190
199
customElements . define ( "test-button-element-non-prop" , ButtonElement )
191
200
192
201
const body = document . body
193
202
body . innerHTML = `<test-button-element-non-prop></test-button-element-non-prop>`
194
203
195
- const testEl = body . querySelector (
204
+ const element = body . querySelector (
196
205
"test-button-element-non-prop" ,
197
206
) as HTMLElement & { text : string }
198
- testEl . style . backgroundColor = "red"
199
- testEl . style . visibility = "hidden"
200
- testEl . id = "test-button-id"
207
+ element . style . backgroundColor = "red"
208
+ element . style . visibility = "hidden"
209
+ element . id = "test-button-id"
201
210
202
- await flushPromises ( )
211
+ await wait ( )
203
212
204
- expect ( testEl ) . toHaveStyle ( "background-color: red;" )
205
- expect ( testEl ) . not . toBeVisible ( )
206
- expect ( body . querySelector ( "#test-button-id" ) ) . toBe ( testEl )
213
+ expect ( element ) . toHaveStyle ( "background-color: red;" )
214
+ expect ( element ) . not . toBeVisible ( )
215
+ expect ( body . querySelector ( "#test-button-id" ) ) . toBe ( element )
207
216
} )
208
217
} )
0 commit comments