Skip to content

Commit

Permalink
test: merge edge ssr tests (#39924)
Browse files Browse the repository at this point in the history
- Group edge ssr tests, merge `edge-vs.-non-edge-api-route-priority` and `react-18-streaming-ssr` into 1 e2e test suite
- Add rewrite case to edge ssr in switchable runtime
  • Loading branch information
huozhi committed Aug 24, 2022
1 parent bd82f69 commit e2a5b09
Show file tree
Hide file tree
Showing 18 changed files with 221 additions and 206 deletions.
3 changes: 2 additions & 1 deletion .github/workflows/build_test_deploy.yml
Expand Up @@ -1222,7 +1222,8 @@ jobs:
- run: TEST_WASM=true xvfb-run node run-tests.js test/integration/production/test/index.test.js
if: ${{needs.build.outputs.docsChange == 'nope'}}

- run: TEST_WASM=true xvfb-run node run-tests.js test/production/react-18-streaming-ssr/index.test.ts
# test wasm parsing for runtime in page config
- run: TEST_WASM=true xvfb-run node run-tests.js test/e2e/streaming-ssr/index.test.ts
if: ${{needs.build.outputs.docsChange == 'nope'}}

# Build binaries for publishing
Expand Down
33 changes: 0 additions & 33 deletions test/e2e/edge-vs.-non-edge-api-route-priority/index.test.ts

This file was deleted.

180 changes: 180 additions & 0 deletions test/e2e/streaming-ssr/index.test.ts
@@ -0,0 +1,180 @@
import { join } from 'path'
import { createNext, FileRef } from 'e2e-utils'
import { NextInstance } from 'test/lib/next-modes/base'
import {
fetchViaHTTP,
findPort,
initNextServerScript,
killApp,
renderViaHTTP,
} from 'next-test-utils'

const react18Deps = {
react: '^18.0.0',
'react-dom': '^18.0.0',
}

const isNextProd = !(global as any).isNextDev && !(global as any).isNextDeploy

describe('react 18 streaming SSR with custom next configs', () => {
let next: NextInstance

beforeAll(async () => {
next = await createNext({
files: {
pages: new FileRef(join(__dirname, 'streaming-ssr/pages')),
},
nextConfig: require(join(__dirname, 'streaming-ssr/next.config.js')),
dependencies: react18Deps,
installCommand: 'npm install',
})
})
afterAll(() => next.destroy())

it('should match more specific route along with dynamic routes', async () => {
const res1 = await fetchViaHTTP(next.url, '/api/user/login')
const res2 = await fetchViaHTTP(next.url, '/api/user/any')
expect(await res1.text()).toBe('login')
expect(await res2.text()).toBe('[id]')
})

it('should render styled-jsx styles in streaming', async () => {
const html = await renderViaHTTP(next.url, '/')
expect(html).toContain('color:blue')
})

it('should redirect paths without trailing-slash and render when slash is appended', async () => {
const page = '/hello'
const redirectRes = await fetchViaHTTP(
next.url,
page,
{},
{ redirect: 'manual' }
)
const res = await fetchViaHTTP(next.url, page + '/')
const html = await res.text()

expect(redirectRes.status).toBe(308)
expect(res.status).toBe(200)
expect(html).toContain('hello nextjs')
expect(html).toContain('home')
})

it('should render multi-byte characters correctly in streaming', async () => {
const html = await renderViaHTTP(next.url, '/multi-byte')
expect(html).toContain('マルチバイト'.repeat(28))
})
})

if (isNextProd) {
describe('react 18 streaming SSR with custom server', () => {
let next
let server
let appPort
beforeAll(async () => {
next = await createNext({
files: {
pages: new FileRef(join(__dirname, 'custom-server/pages')),
'server.js': new FileRef(join(__dirname, 'custom-server/server.js')),
},
nextConfig: require(join(__dirname, 'custom-server/next.config.js')),
dependencies: react18Deps,
})
await next.stop()

const testServer = join(next.testDir, 'server.js')
appPort = await findPort()
server = await initNextServerScript(
testServer,
/Listening/,
{
...process.env,
PORT: appPort,
},
undefined,
{
cwd: next.testDir,
}
)
})
afterAll(async () => {
await next.destroy()
if (server) await killApp(server)
})
it('should render page correctly under custom server', async () => {
const html = await renderViaHTTP(appPort, '/')
expect(html).toContain('streaming')
})
})

describe('react 18 streaming SSR in minimal mode with node runtime', () => {
let next: NextInstance

beforeAll(async () => {
if (isNextProd) {
process.env.NEXT_PRIVATE_MINIMAL_MODE = '1'
}

next = await createNext({
files: {
'pages/index.js': `
export default function Page() {
return <p>streaming</p>
}
export async function getServerSideProps() {
return { props: {} }
}`,
},
nextConfig: {
experimental: {
runtime: 'nodejs',
},
webpack(config, { nextRuntime }) {
const path = require('path')
const fs = require('fs')

const runtimeFilePath = path.join(__dirname, 'runtimes.txt')
let runtimeContent = ''

try {
runtimeContent = fs.readFileSync(runtimeFilePath, 'utf8')
runtimeContent += '\n'
} catch (_) {}

runtimeContent += nextRuntime || 'client'

fs.writeFileSync(runtimeFilePath, runtimeContent)
return config
},
},
dependencies: react18Deps,
})
})
afterAll(() => {
if (isNextProd) {
delete process.env.NEXT_PRIVATE_MINIMAL_MODE
}
next.destroy()
})

it('should pass correct nextRuntime values', async () => {
const content = await next.readFile('runtimes.txt')
expect(content.split('\n').sort()).toEqual(['client', 'edge', 'nodejs'])
})

it('should generate html response by streaming correctly', async () => {
const html = await renderViaHTTP(next.url, '/')
expect(html).toContain('streaming')
})

if (isNextProd) {
it('should have generated a static 404 page', async () => {
expect(await next.readFile('.next/server/pages/404.html')).toBeTruthy()

const res = await fetchViaHTTP(next.url, '/non-existent')
expect(res.status).toBe(404)
expect(await res.text()).toContain('This page could not be found')
})
}
})
}
3 changes: 3 additions & 0 deletions test/e2e/streaming-ssr/streaming-ssr/next.config.js
@@ -0,0 +1,3 @@
module.exports = {
trailingSlash: true,
}
7 changes: 7 additions & 0 deletions test/e2e/streaming-ssr/streaming-ssr/pages/api/user/[id].js
@@ -0,0 +1,7 @@
export default async function handler() {
return new Response('[id]')
}

export const config = {
runtime: 'experimental-edge',
}
3 changes: 3 additions & 0 deletions test/e2e/streaming-ssr/streaming-ssr/pages/api/user/login.js
@@ -0,0 +1,3 @@
export default async function handler(_, res) {
res.send('login')
}
9 changes: 9 additions & 0 deletions test/e2e/switchable-runtime/index.test.ts
Expand Up @@ -286,6 +286,10 @@ describe('Switchable runtime', () => {
isStatic: false,
isEdge: true,
})
await testRoute(context.appPort, '/rewrite/edge', {
isStatic: false,
isEdge: true,
})
})

// TODO: edge rsc in app dir
Expand All @@ -305,6 +309,11 @@ describe('Switchable runtime', () => {
text = await response.text()
expect(text).toMatch(/Returned by Edge API Route .+\/api\/edge/)

// Rewrite should also work
response = await fetchViaHTTP(context.appPort, 'rewrite/api/edge')
text = await response.text()
expect(text).toMatch(/Returned by Edge API Route .+\/api\/edge/)

if (!(global as any).isNextDeploy) {
const manifest = await readJson(
join(context.appDir, '.next/server/middleware-manifest.json')
Expand Down
15 changes: 15 additions & 0 deletions test/e2e/switchable-runtime/next.config.js
@@ -1,7 +1,22 @@
/** @type {import('next').NextConfig} */
module.exports = {
reactStrictMode: true,
experimental: {
appDir: true,
serverComponents: true,
},
async rewrites() {
return {
afterFiles: [
{
source: '/rewrite/edge',
destination: '/edge',
},
{
source: '/rewrite/api/edge',
destination: '/api/edge',
},
],
}
},
}
Expand Up @@ -239,7 +239,7 @@ describe('ServerSide Props Preview Mode', () => {
expect(cookies.length).toBe(2)
})

/** @type import('next-webdriver').Chain */
/** @type {import('next-webdriver').Chain} */
let browser
it('should start the client-side browser', async () => {
browser = await webdriver(
Expand Down
2 changes: 1 addition & 1 deletion test/integration/prerender-preview/test/index.test.js
Expand Up @@ -300,7 +300,7 @@ describe('Prerender Preview Mode', () => {
expect(cookies.length).toBe(2)
})

/** @type import('next-webdriver').Chain */
/** @type {import('next-webdriver').Chain} */
let browser
it('should start the client-side browser', async () => {
browser = await webdriver(
Expand Down

0 comments on commit e2a5b09

Please sign in to comment.