未验证 提交 b747a366 编写于 作者: J Joe Haddad 提交者: GitHub

Fix Preview Mode in `<iframe>` (#11638)

上级 d97ac9ff
......@@ -391,7 +391,8 @@ function setPreviewData<T>(
: []),
serialize(COOKIE_NAME_PRERENDER_BYPASS, options.previewModeId, {
httpOnly: true,
sameSite: 'lax',
sameSite: process.env.NODE_ENV !== 'development' ? 'none' : 'lax',
secure: process.env.NODE_ENV !== 'development',
path: '/',
...(options.maxAge !== undefined
? ({ maxAge: options.maxAge } as CookieSerializeOptions)
......@@ -399,7 +400,8 @@ function setPreviewData<T>(
}),
serialize(COOKIE_NAME_PRERENDER_DATA, payload, {
httpOnly: true,
sameSite: 'lax',
sameSite: process.env.NODE_ENV !== 'development' ? 'none' : 'lax',
secure: process.env.NODE_ENV !== 'development',
path: '/',
...(options.maxAge !== undefined
? ({ maxAge: options.maxAge } as CookieSerializeOptions)
......@@ -430,7 +432,8 @@ function clearPreviewData<T>(res: NextApiResponse<T>): NextApiResponse<T> {
// `Max-Age: 0` is not valid, thus ignored, and the cookie is persisted.
expires: new Date(0),
httpOnly: true,
sameSite: 'lax',
sameSite: process.env.NODE_ENV !== 'development' ? 'none' : 'lax',
secure: process.env.NODE_ENV !== 'development',
path: '/',
}),
serialize(COOKIE_NAME_PRERENDER_DATA, '', {
......@@ -439,7 +442,8 @@ function clearPreviewData<T>(res: NextApiResponse<T>): NextApiResponse<T> {
// `Max-Age: 0` is not valid, thus ignored, and the cookie is persisted.
expires: new Date(0),
httpOnly: true,
sameSite: 'lax',
sameSite: process.env.NODE_ENV !== 'development' ? 'none' : 'lax',
secure: process.env.NODE_ENV !== 'development',
path: '/',
}),
])
......
......@@ -115,7 +115,7 @@
"@types/ci-info": "2.0.0",
"@types/compression": "0.0.36",
"@types/content-type": "1.1.3",
"@types/cookie": "0.3.2",
"@types/cookie": "0.3.3",
"@types/cross-spawn": "6.0.0",
"@types/dotenv": "8.2.0",
"@types/etag": "1.8.0",
......
......@@ -68,16 +68,16 @@ function runTests(startServer = nextStart) {
const res = await fetchViaHTTP(appPort, '/api/preview', { lets: 'goooo' })
expect(res.status).toBe(200)
const cookies = res.headers
.get('set-cookie')
.split(',')
.map(cookie.parse)
const originalCookies = res.headers.get('set-cookie').split(',')
const cookies = originalCookies.map(cookie.parse)
expect(originalCookies.every(c => c.includes('; Secure;')))
expect(cookies.length).toBe(2)
expect(cookies[0]).toMatchObject({ Path: '/', SameSite: 'Lax' })
expect(cookies[0]).toMatchObject({ Path: '/', SameSite: 'None' })
expect(cookies[0]).toHaveProperty('__prerender_bypass')
expect(cookies[0]).not.toHaveProperty('Max-Age')
expect(cookies[1]).toMatchObject({ Path: '/', SameSite: 'Lax' })
expect(cookies[1]).toMatchObject({ Path: '/', SameSite: 'None' })
expect(cookies[1]).toHaveProperty('__next_preview_data')
expect(cookies[1]).not.toHaveProperty('Max-Age')
......@@ -142,14 +142,14 @@ function runTests(startServer = nextStart) {
expect(cookies.length).toBe(2)
expect(cookies[0]).toMatchObject({
Path: '/',
SameSite: 'Lax',
SameSite: 'None',
Expires: 'Thu 01 Jan 1970 00:00:00 GMT',
})
expect(cookies[0]).toHaveProperty('__prerender_bypass')
expect(cookies[0]).not.toHaveProperty('Max-Age')
expect(cookies[1]).toMatchObject({
Path: '/',
SameSite: 'Lax',
SameSite: 'None',
Expires: 'Thu 01 Jan 1970 00:00:00 GMT',
})
expect(cookies[1]).toHaveProperty('__next_preview_data')
......@@ -162,47 +162,7 @@ function runTests(startServer = nextStart) {
expect(await res.text()).toBe('too big')
})
/** @type import('next-webdriver').Chain */
let browser
it('should start the client-side browser', async () => {
browser = await webdriver(
appPort,
'/api/preview?' + qs.stringify({ client: 'mode' })
)
})
it('should fetch preview data on SSR', async () => {
await browser.get(`http://localhost:${appPort}/`)
await browser.waitForElementByCss('#props-pre')
// expect(await browser.elementById('props-pre').text()).toBe('Has No Props')
// await new Promise(resolve => setTimeout(resolve, 2000))
expect(await browser.elementById('props-pre').text()).toBe(
'true and {"client":"mode"}'
)
})
it('should fetch preview data on CST', async () => {
await browser.get(`http://localhost:${appPort}/to-index`)
await browser.waitForElementByCss('#to-index')
await browser.eval('window.itdidnotrefresh = "hello"')
await browser.elementById('to-index').click()
await browser.waitForElementByCss('#props-pre')
expect(await browser.eval('window.itdidnotrefresh')).toBe('hello')
expect(await browser.elementById('props-pre').text()).toBe(
'true and {"client":"mode"}'
)
})
it('should fetch prerendered data', async () => {
await browser.get(`http://localhost:${appPort}/api/reset`)
await browser.get(`http://localhost:${appPort}/`)
await browser.waitForElementByCss('#props-pre')
expect(await browser.elementById('props-pre').text()).toBe('false and null')
})
afterAll(async () => {
await browser.close()
await killApp(app)
})
}
......@@ -273,7 +233,49 @@ describe('ServerSide Props Preview Mode', () => {
expect(cookies.length).toBe(2)
})
/** @type import('next-webdriver').Chain */
let browser
it('should start the client-side browser', async () => {
browser = await webdriver(
appPort,
'/api/preview?' + qs.stringify({ client: 'mode' })
)
})
it('should fetch preview data on SSR', async () => {
await browser.get(`http://localhost:${appPort}/`)
await browser.waitForElementByCss('#props-pre')
// expect(await browser.elementById('props-pre').text()).toBe('Has No Props')
// await new Promise(resolve => setTimeout(resolve, 2000))
expect(await browser.elementById('props-pre').text()).toBe(
'true and {"client":"mode"}'
)
})
it('should fetch preview data on CST', async () => {
await browser.get(`http://localhost:${appPort}/to-index`)
await browser.waitForElementByCss('#to-index')
await browser.eval('window.itdidnotrefresh = "hello"')
await browser.elementById('to-index').click()
await browser.waitForElementByCss('#props-pre')
expect(await browser.eval('window.itdidnotrefresh')).toBe('hello')
expect(await browser.elementById('props-pre').text()).toBe(
'true and {"client":"mode"}'
)
})
it('should fetch prerendered data', async () => {
await browser.get(`http://localhost:${appPort}/api/reset`)
await browser.get(`http://localhost:${appPort}/`)
await browser.waitForElementByCss('#props-pre')
expect(await browser.elementById('props-pre').text()).toBe(
'false and null'
)
})
afterAll(async () => {
await browser.close()
await killApp(app)
})
})
......
......@@ -74,16 +74,16 @@ function runTests(startServer = nextStart) {
const res = await fetchViaHTTP(appPort, '/api/preview', { lets: 'goooo' })
expect(res.status).toBe(200)
const cookies = res.headers
.get('set-cookie')
.split(',')
.map(cookie.parse)
const originalCookies = res.headers.get('set-cookie').split(',')
const cookies = originalCookies.map(cookie.parse)
expect(originalCookies.every(c => c.includes('; Secure;')))
expect(cookies.length).toBe(2)
expect(cookies[0]).toMatchObject({ Path: '/', SameSite: 'Lax' })
expect(cookies[0]).toMatchObject({ Path: '/', SameSite: 'None' })
expect(cookies[0]).toHaveProperty('__prerender_bypass')
expect(cookies[0]).not.toHaveProperty('Max-Age')
expect(cookies[1]).toMatchObject({ Path: '/', SameSite: 'Lax' })
expect(cookies[1]).toMatchObject({ Path: '/', SameSite: 'None' })
expect(cookies[1]).toHaveProperty('__next_preview_data')
expect(cookies[1]).not.toHaveProperty('Max-Age')
......@@ -148,61 +148,21 @@ function runTests(startServer = nextStart) {
expect(cookies.length).toBe(2)
expect(cookies[0]).toMatchObject({
Path: '/',
SameSite: 'Lax',
SameSite: 'None',
Expires: 'Thu 01 Jan 1970 00:00:00 GMT',
})
expect(cookies[0]).toHaveProperty('__prerender_bypass')
expect(cookies[0]).not.toHaveProperty('Max-Age')
expect(cookies[1]).toMatchObject({
Path: '/',
SameSite: 'Lax',
SameSite: 'None',
Expires: 'Thu 01 Jan 1970 00:00:00 GMT',
})
expect(cookies[1]).toHaveProperty('__next_preview_data')
expect(cookies[1]).not.toHaveProperty('Max-Age')
})
/** @type import('next-webdriver').Chain */
let browser
it('should start the client-side browser', async () => {
browser = await webdriver(
appPort,
'/api/preview?' + qs.stringify({ client: 'mode' })
)
})
it('should fetch preview data on SSR', async () => {
await browser.get(`http://localhost:${appPort}/`)
await browser.waitForElementByCss('#props-pre')
// expect(await browser.elementById('props-pre').text()).toBe('Has No Props')
// await new Promise(resolve => setTimeout(resolve, 2000))
expect(await browser.elementById('props-pre').text()).toBe(
'true and {"client":"mode"}'
)
})
it('should fetch preview data on CST', async () => {
await browser.get(`http://localhost:${appPort}/to-index`)
await browser.waitForElementByCss('#to-index')
await browser.eval('window.itdidnotrefresh = "hello"')
await browser.elementById('to-index').click()
await browser.waitForElementByCss('#props-pre')
expect(await browser.eval('window.itdidnotrefresh')).toBe('hello')
expect(await browser.elementById('props-pre').text()).toBe(
'true and {"client":"mode"}'
)
})
it('should fetch prerendered data', async () => {
await browser.get(`http://localhost:${appPort}/api/reset`)
await browser.get(`http://localhost:${appPort}/`)
await browser.waitForElementByCss('#props-pre')
expect(await browser.elementById('props-pre').text()).toBe('false and null')
})
afterAll(async () => {
await browser.close()
await killApp(app)
})
}
......@@ -273,7 +233,49 @@ describe('Prerender Preview Mode', () => {
expect(cookies.length).toBe(2)
})
/** @type import('next-webdriver').Chain */
let browser
it('should start the client-side browser', async () => {
browser = await webdriver(
appPort,
'/api/preview?' + qs.stringify({ client: 'mode' })
)
})
it('should fetch preview data on SSR', async () => {
await browser.get(`http://localhost:${appPort}/`)
await browser.waitForElementByCss('#props-pre')
// expect(await browser.elementById('props-pre').text()).toBe('Has No Props')
// await new Promise(resolve => setTimeout(resolve, 2000))
expect(await browser.elementById('props-pre').text()).toBe(
'true and {"client":"mode"}'
)
})
it('should fetch preview data on CST', async () => {
await browser.get(`http://localhost:${appPort}/to-index`)
await browser.waitForElementByCss('#to-index')
await browser.eval('window.itdidnotrefresh = "hello"')
await browser.elementById('to-index').click()
await browser.waitForElementByCss('#props-pre')
expect(await browser.eval('window.itdidnotrefresh')).toBe('hello')
expect(await browser.elementById('props-pre').text()).toBe(
'true and {"client":"mode"}'
)
})
it('should fetch prerendered data', async () => {
await browser.get(`http://localhost:${appPort}/api/reset`)
await browser.get(`http://localhost:${appPort}/`)
await browser.waitForElementByCss('#props-pre')
expect(await browser.elementById('props-pre').text()).toBe(
'false and null'
)
})
afterAll(async () => {
await browser.close()
await killApp(app)
})
})
......
......@@ -2524,10 +2524,10 @@
resolved "https://registry.yarnpkg.com/@types/content-type/-/content-type-1.1.3.tgz#3688bd77fc12f935548eef102a4e34c512b03a07"
integrity sha512-pv8VcFrZ3fN93L4rTNIbbUzdkzjEyVMp5mPVjsFfOYTDOZMZiZ8P1dhu+kEv3faYyKzZgLlSvnyQNFg+p/v5ug==
"@types/cookie@0.3.2":
version "0.3.2"
resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.3.2.tgz#453f4b14b25da6a8ea4494842dedcbf0151deef9"
integrity sha512-aHQA072E10/8iUQsPH7mQU/KUyQBZAGzTVRCUvnSz8mSvbrYsP4xEO2RSA0Pjltolzi0j8+8ixrm//Hr4umPzw==
"@types/cookie@0.3.3":
version "0.3.3"
resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.3.3.tgz#85bc74ba782fb7aa3a514d11767832b0e3bc6803"
integrity sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==
"@types/cross-spawn@6.0.0":
version "6.0.0"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册