@@ -21,6 +21,26 @@ describe("reactFromHtml E2E tests", async () => {
2121 expect ( documentElement . innerHTML ) . toMatchSnapshot ( ) ;
2222 } ) ;
2323
24+ it ( "Should not re-hydrate already hydrated components on multiple `reactFromHtml()` calls" , async ( ) => {
25+ const componentName : string = "myComponent" ;
26+
27+ const mockCall = jest . fn ( ) ;
28+ const hydrator = async ( ) => {
29+ mockCall ( ) ;
30+
31+ return React . createElement ( "span" , { } , "hydrated component" ) ;
32+ } ;
33+
34+ const hydrators = { [ `.${ componentName } ` ] : hydrator } ;
35+ const documentElement = document . createElement ( "div" ) ;
36+
37+ documentElement . innerHTML = `<div class="${ componentName } "></div>` ;
38+
39+ await reactFromHtml ( documentElement , hydrators ) ;
40+ await reactFromHtml ( documentElement , hydrators ) ;
41+ expect ( mockCall ) . toBeCalledTimes ( 1 ) ;
42+ } ) ;
43+
2444 it ( "Should work for nested hydratables" , async ( ) => {
2545 const mockCall = jest . fn ( ) ;
2646 const hydrators : IHydrator = {
@@ -71,4 +91,58 @@ describe("reactFromHtml E2E tests", async () => {
7191
7292 expect ( documentElement . innerHTML ) . toMatchSnapshot ( ) ;
7393 } ) ;
94+
95+ it ( "Should not mutate static markup" , async ( ) => {
96+ const componentName : string = "myComponent" ;
97+
98+ const hydrator = async ( ) => {
99+ return React . createElement ( "span" , { } , "hydrated component" ) ;
100+ } ;
101+
102+ const hydrators = { [ `.${ componentName } ` ] : hydrator } ;
103+ const documentElement = document . createElement ( "div" ) ;
104+
105+ documentElement . innerHTML = `
106+ <div>
107+ <p>Static HTML, with some <b style="font-weight:bold;">interesting</b> markup</p>
108+ <div data-hydratable="test-${ componentName } "></div>
109+ </div>` ;
110+
111+ await reactFromHtml ( documentElement , hydrators ) ;
112+
113+ expect ( documentElement . innerHTML ) . toMatchSnapshot ( ) ;
114+ } ) ;
115+
116+ it ( "Should not mutate static markup of nested children" , async ( ) => {
117+ const mockCall = jest . fn ( ) ;
118+ const hydrators : IHydrator = {
119+ [ `.Parent` ] : async ( el : Element , hydrate ) => {
120+ mockCall ( ) ;
121+
122+ return React . createElement ( "span" , { } , await hydrate ( el ) ) ;
123+ } ,
124+ } ;
125+
126+ const documentElement = document . createElement ( "div" ) ;
127+
128+ documentElement . innerHTML = `
129+ <div class="Parent">
130+ <p>Static HTML, with some <b style="font-weight:bold;">interesting</b> markup</p>
131+ <form>
132+ <input type="checkbox" name="confirm" value="confirmed" checked>
133+ <select id="favourite-color">
134+ <option value="red">red</option>
135+ <option value="green" selected>green</option>
136+ <option value="blue">blue</option>
137+ </select>
138+ <textarea name="message">Default value</textarea>
139+ </form>
140+ </div>
141+ ` ;
142+
143+ await reactFromHtml ( documentElement , hydrators ) ;
144+
145+ expect ( documentElement . innerHTML ) . toMatchSnapshot ( ) ;
146+ expect ( mockCall ) . toBeCalledTimes ( 1 ) ;
147+ } ) ;
74148} ) ;
0 commit comments