Skip to content

Commit c41fff6

Browse files
committed
test(interop): cover runtime SSR-to-hydrate chain
1 parent 1cad3a6 commit c41fff6

File tree

1 file changed

+98
-1
lines changed

1 file changed

+98
-1
lines changed

test/interop.it.test.ts

Lines changed: 98 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,35 @@
11
import { render } from '@fictjs/runtime'
22
import { createSignal } from '@fictjs/runtime/advanced'
33
import { __fictDisableSSR, __fictEnableSSR } from '@fictjs/runtime/internal'
4+
import React, { useState } from 'react'
45
import { afterEach, describe, expect, it } from 'vitest'
56

6-
import { installReactIslands, reactify$ } from '../src'
7+
import { installReactIslands, reactify, reactify$ } from '../src'
78
import { encodePropsForAttribute } from '../src/serialization'
89

910
const tick = async (ms = 0) => {
1011
await new Promise((resolve) => setTimeout(resolve, ms))
1112
}
1213

14+
const waitForExpectation = async (assertion: () => void, timeoutMs = 1_000): Promise<void> => {
15+
const deadline = Date.now() + timeoutMs
16+
let lastError: unknown
17+
18+
while (Date.now() < deadline) {
19+
try {
20+
assertion()
21+
return
22+
} catch (error) {
23+
lastError = error
24+
await tick(10)
25+
}
26+
}
27+
28+
throw lastError instanceof Error
29+
? lastError
30+
: new Error('Timed out waiting for asynchronous expectation.')
31+
}
32+
1333
afterEach(() => {
1434
document.body.innerHTML = ''
1535
__fictDisableSSR()
@@ -86,4 +106,81 @@ describe('interop IT', () => {
86106

87107
stop()
88108
})
109+
110+
it('hydrates SSR host through runtime reactify path and reuses existing DOM nodes', async () => {
111+
const RuntimeHydrationIsland = reactify(({ initial }: { initial: number }) => {
112+
const [count, setCount] = useState(initial)
113+
114+
return React.createElement(
115+
'button',
116+
{
117+
id: 'runtime-hydration-button',
118+
onClick: () => setCount((value) => value + 1),
119+
},
120+
`runtime:${count}`,
121+
)
122+
})
123+
124+
function App() {
125+
return {
126+
type: RuntimeHydrationIsland,
127+
props: {
128+
initial: 2,
129+
},
130+
}
131+
}
132+
133+
const ssrContainer = document.createElement('div')
134+
document.body.appendChild(ssrContainer)
135+
136+
__fictEnableSSR()
137+
const disposeSSR = render(() => ({ type: App, props: {} }), ssrContainer)
138+
__fictDisableSSR()
139+
140+
const ssrHost = ssrContainer.querySelector('[data-fict-react-host]') as HTMLElement | null
141+
expect(ssrHost).not.toBeNull()
142+
expect(ssrHost?.getAttribute('data-fict-react-ssr')).toBe('1')
143+
expect(ssrHost?.innerHTML).toContain('runtime:2')
144+
const ssrHostInnerHtml = ssrHost?.innerHTML ?? ''
145+
disposeSSR()
146+
147+
const clientContainer = document.createElement('div')
148+
document.body.appendChild(clientContainer)
149+
150+
const disposeClient = render(() => ({ type: App, props: {} }), clientContainer)
151+
const clientHost = clientContainer.querySelector('[data-fict-react-host]') as HTMLElement | null
152+
expect(clientHost).not.toBeNull()
153+
expect(clientHost?.getAttribute('data-fict-react-ssr')).toBe('1')
154+
155+
// Fill the runtime host with server-rendered HTML before load-strategy mount runs.
156+
clientHost!.innerHTML = ssrHostInnerHtml
157+
158+
const preHydrationButton = clientHost!.querySelector(
159+
'#runtime-hydration-button',
160+
) as HTMLButtonElement | null
161+
expect(preHydrationButton).not.toBeNull()
162+
163+
let nativeClicks = 0
164+
preHydrationButton!.addEventListener('click', () => {
165+
nativeClicks += 1
166+
})
167+
168+
await waitForExpectation(() => {
169+
expect(clientHost?.getAttribute('data-fict-react-mounted')).toBe('1')
170+
})
171+
172+
const hydratedButton = clientHost!.querySelector(
173+
'#runtime-hydration-button',
174+
) as HTMLButtonElement | null
175+
expect(hydratedButton).toBe(preHydrationButton)
176+
177+
hydratedButton?.click()
178+
await waitForExpectation(() => {
179+
expect(hydratedButton?.textContent).toBe('runtime:3')
180+
})
181+
182+
expect(nativeClicks).toBe(1)
183+
184+
disposeClient()
185+
})
89186
})

0 commit comments

Comments
 (0)