-
Notifications
You must be signed in to change notification settings - Fork 26.1k
/
streaming.js
114 lines (100 loc) · 3.69 KB
/
streaming.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/* eslint-env jest */
import webdriver from 'next-webdriver'
import { fetchViaHTTP } from 'next-test-utils'
async function resolveStreamResponse(response, onData) {
let result = ''
onData = onData || (() => {})
await new Promise((resolve) => {
response.body.on('data', (chunk) => {
result += chunk.toString()
onData(chunk.toString(), result)
})
response.body.on('end', resolve)
})
return result
}
export default function (context) {
it('should disable cache for fizz pages', async () => {
const urls = ['/', '/next-api/image', '/next-api/link']
await Promise.all(
urls.map(async (url) => {
const { headers } = await fetchViaHTTP(context.appPort, url)
expect(headers.get('cache-control')).toBe(
'no-cache, no-store, max-age=0, must-revalidate'
)
})
)
})
it('should support streaming for fizz response', async () => {
await fetchViaHTTP(context.appPort, '/streaming', null, {}).then(
async (response) => {
let gotFallback = false
let gotData = false
await resolveStreamResponse(response, (_, result) => {
gotData = result.includes('next_streaming_data')
if (!gotFallback) {
gotFallback = result.includes('next_streaming_fallback')
if (gotFallback) {
expect(gotData).toBe(false)
}
}
})
expect(gotFallback).toBe(true)
expect(gotData).toBe(true)
}
)
// Should end up with "next_streaming_data".
const browser = await webdriver(context.appPort, '/streaming')
const content = await browser.eval(`window.document.body.innerText`)
expect(content).toMatchInlineSnapshot('"next_streaming_data"')
})
it('should support streaming for flight response', async () => {
await fetchViaHTTP(context.appPort, '/?__flight__=1').then(
async (response) => {
const result = await resolveStreamResponse(response)
expect(result).toContain('component:index.server')
}
)
})
it('should support partial hydration with inlined server data', async () => {
await fetchViaHTTP(context.appPort, '/partial-hydration', null, {}).then(
async (response) => {
let gotFallback = false
let gotData = false
let gotInlinedData = false
await resolveStreamResponse(response, (_, result) => {
gotInlinedData = result.includes('self.__next_s=')
gotData = result.includes('next_streaming_data')
if (!gotFallback) {
gotFallback = result.includes('next_streaming_fallback')
if (gotFallback) {
expect(gotData).toBe(false)
expect(gotInlinedData).toBe(false)
}
}
})
expect(gotFallback).toBe(true)
expect(gotData).toBe(true)
expect(gotInlinedData).toBe(true)
}
)
// Should end up with "next_streaming_data".
const browser = await webdriver(context.appPort, '/partial-hydration')
const content = await browser.eval(`window.document.body.innerText`)
expect(content).toContain('next_streaming_data')
// Should support partial hydration: the boundary should still be pending
// while another part is hydrated already.
expect(await browser.eval(`window.partial_hydration_suspense_result`)).toBe(
'next_streaming_fallback'
)
expect(await browser.eval(`window.partial_hydration_counter_result`)).toBe(
'count: 1'
)
})
it('should flush the suffix at the very end', async () => {
await fetchViaHTTP(context.appPort, '/').then(async (response) => {
const result = await resolveStreamResponse(response)
expect(result).toMatch(/<\/body><\/html>/)
})
})
}