9fff7e321c
Revert some code in #47379 and finalize HOC support. We should require the HOC to return a "use server" function, so there's no need to compile the function call specially now. To make that wrapping logic work, we need to allow passing a server reference to another server reference. This usually happens in the function closure in the HOC case, but ideally it's also allowed to directly pass it as an argument. This requires adding React server DOM's `encodeReply` and `decodeReply` and other corresponding changes, including adding `busboy` (can probably be vendored?) as we need to parse the multipart body now. fix NEXT-808 ([link](https://linear.app/vercel/issue/NEXT-808)) ([link](https://linear.app/vercel/issue/NEXT-808))
135 lines
4.2 KiB
TypeScript
135 lines
4.2 KiB
TypeScript
import { createNextDescribe } from 'e2e-utils'
|
|
import { check } from 'next-test-utils'
|
|
|
|
createNextDescribe(
|
|
'app-dir action handling',
|
|
{
|
|
files: __dirname,
|
|
skipDeployment: true,
|
|
},
|
|
({ next, isNextDev }) => {
|
|
it('should handle basic actions correctly', async () => {
|
|
const browser = await next.browser('/server')
|
|
|
|
const cnt = await browser.elementByCss('h1').text()
|
|
expect(cnt).toBe('0')
|
|
|
|
await browser.elementByCss('#inc').click()
|
|
await check(() => browser.elementByCss('h1').text(), '1')
|
|
|
|
await browser.elementByCss('#inc').click()
|
|
await check(() => browser.elementByCss('h1').text(), '2')
|
|
|
|
await browser.elementByCss('#double').click()
|
|
await check(() => browser.elementByCss('h1').text(), '4')
|
|
|
|
await browser.elementByCss('#dec').click()
|
|
await check(() => browser.elementByCss('h1').text(), '3')
|
|
})
|
|
|
|
it('should support headers and cookies', async () => {
|
|
const browser = await next.browser('/header')
|
|
|
|
await browser.elementByCss('#cookie').click()
|
|
await check(async () => {
|
|
const res = (await browser.elementByCss('h1').text()) || ''
|
|
const id = res.split(':')
|
|
return id[0] === id[1] && id[0] ? 'same' : 'different'
|
|
}, 'same')
|
|
|
|
await browser.elementByCss('#header').click()
|
|
await check(async () => {
|
|
const res = (await browser.elementByCss('h1').text()) || ''
|
|
return res.includes('Mozilla') ? 'UA' : ''
|
|
}, 'UA')
|
|
})
|
|
|
|
it('should support formData and redirect', async () => {
|
|
const browser = await next.browser('/server')
|
|
|
|
await browser.eval(`document.getElementById('name').value = 'test'`)
|
|
await browser.elementByCss('#submit').click()
|
|
|
|
await check(() => {
|
|
return browser.eval('window.location.pathname + window.location.search')
|
|
}, '/header?name=test')
|
|
})
|
|
|
|
it('should support notFound', async () => {
|
|
const browser = await next.browser('/server')
|
|
|
|
await browser.elementByCss('#nowhere').click()
|
|
|
|
await check(() => {
|
|
return browser.elementByCss('h1').text()
|
|
}, 'my-not-found')
|
|
})
|
|
|
|
it('should support hoc auth wrappers', async () => {
|
|
const browser = await next.browser('/header')
|
|
await await browser.eval(`document.cookie = 'auth=0'`)
|
|
|
|
await browser.elementByCss('#authed').click()
|
|
|
|
await check(() => {
|
|
return browser.elementByCss('h1').text()
|
|
}, 'Error: Unauthorized request')
|
|
|
|
await await browser.eval(`document.cookie = 'auth=1'`)
|
|
|
|
await browser.elementByCss('#authed').click()
|
|
|
|
await check(() => {
|
|
return browser.elementByCss('h1').text()
|
|
}, 'Prefix: HELLO, WORLD')
|
|
})
|
|
|
|
it('should support importing actions in client components', async () => {
|
|
const browser = await next.browser('/client')
|
|
|
|
const cnt = await browser.elementByCss('h1').text()
|
|
expect(cnt).toBe('0')
|
|
|
|
await browser.elementByCss('#inc').click()
|
|
await check(() => browser.elementByCss('h1').text(), '1')
|
|
|
|
await browser.elementByCss('#inc').click()
|
|
await check(() => browser.elementByCss('h1').text(), '2')
|
|
|
|
await browser.elementByCss('#double').click()
|
|
await check(() => browser.elementByCss('h1').text(), '4')
|
|
|
|
await browser.elementByCss('#dec').click()
|
|
await check(() => browser.elementByCss('h1').text(), '3')
|
|
})
|
|
|
|
if (isNextDev) {
|
|
describe('HMR', () => {
|
|
it('should support updating the action', async () => {
|
|
const filePath = 'app/server/actions.js'
|
|
const origContent = await next.readFile(filePath)
|
|
|
|
try {
|
|
const browser = await next.browser('/server')
|
|
|
|
const cnt = await browser.elementByCss('h1').text()
|
|
expect(cnt).toBe('0')
|
|
|
|
await browser.elementByCss('#inc').click()
|
|
await check(() => browser.elementByCss('h1').text(), '1')
|
|
|
|
await next.patchFile(
|
|
filePath,
|
|
origContent.replace('return value + 1', 'return value + 1000')
|
|
)
|
|
|
|
await browser.elementByCss('#inc').click()
|
|
await check(() => browser.elementByCss('h1').text(), '1001')
|
|
} finally {
|
|
await next.patchFile(filePath, origContent)
|
|
}
|
|
})
|
|
})
|
|
}
|
|
}
|
|
)
|