Files
next.js/test/e2e/url/url.test.ts
Arian Tron 61f56f997c
Some checks failed
Test examples / Test Examples (20) (push) Has been cancelled
Test examples / Test Examples (22) (push) Has been cancelled
Lock Threads / action (push) Has been cancelled
Trigger Release / start (push) Has been cancelled
Stale issue handler / stale (push) Has been cancelled
Update Font Data / create-pull-request (push) Has been cancelled
build-and-deploy / deploy-target (push) Has been cancelled
build-and-deploy / build (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-musl - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-unknown-linux-gnu - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-pc-windows-msvc - node@16 (push) Has been cancelled
build-and-deploy / stable - aarch64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / stable - x86_64-apple-darwin - node@16 (push) Has been cancelled
build-and-deploy / build-wasm (nodejs) (push) Has been cancelled
build-and-deploy / build-wasm (web) (push) Has been cancelled
build-and-deploy / Deploy preview tarball (push) Has been cancelled
build-and-deploy / Potentially publish release (push) Has been cancelled
build-and-deploy / publish-turbopack-npm-packages (push) Has been cancelled
build-and-deploy / Deploy examples (push) Has been cancelled
build-and-deploy / thank you, build (push) Has been cancelled
build-and-deploy / Upload Turbopack Bytesize metrics to Datadog (push) Has been cancelled
Rspack Next.js development integration tests / Rspack integration tests (push) Has been cancelled
Rspack Next.js production integration tests / Rspack integration tests (push) Has been cancelled
Turbopack Next.js development integration tests / Next.js integration tests (push) Has been cancelled
Turbopack Next.js production integration tests / Next.js integration tests (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack development test manifest (push) Has been cancelled
Update Rspack test manifest / Update and upload Rspack production test manifest (push) Has been cancelled
Upload bundler test manifests to areweturboyet.com / Upload test results (push) Has been cancelled
Update React / create-pull-request (push) Has been cancelled
test-e2e-project-reset-cron / reset-test-project (push) Has been cancelled
Notify about the top 15 issues/PRs/feature requests (most reacted) in the last 90 days / run (push) Has been cancelled
first commit
2026-03-10 19:37:31 +03:30

205 lines
6.2 KiB
TypeScript

import { retry } from 'next-test-utils'
import { isNextDev, isNextStart, nextTestSetup } from 'e2e-utils'
// | | Pages Client | Pages Server (SSR,RSC) | API Routes/Middleware/Metadata |
// |---------|-------------------------|-------------------------|--------------------------------|
// | new URL | /_next/static/media/... | /_next/static/media/... | /server/assets/... |
// | import | /_next/static/media/... | /_next/static/media/... | /_next/static/media/... |
// |---------|-------------------------|-------------------------|--------------------------------|
//
// Webpack has
// - a bug where App Router API routes (and Metadata) return client assets for `new URL`s.
// - a bug where Edge Page routes return client assets for `new URL`s.
describe(`Handle new URL asset references`, () => {
const { next, skipped, isTurbopack } = nextTestSetup({
files: __dirname,
env: {
// rely on skew protection when deployed
NEXT_DEPLOYMENT_ID: isNextStart ? 'test-deployment-id' : undefined,
__NEXT_IMMUTABLE_ASSET_TOKEN: isNextStart
? 'test-immutable-tkn-7890'
: undefined,
},
skipDeployment: true,
})
if (skipped) {
return
}
const serverFileRegex = expect.stringMatching(
/file:.*\/.next(\/dev)?\/server\/.*\/vercel.HASH.png$/
)
const serverEdgeUrl = isTurbopack
? `blob:server/edge/assets/vercel.HASH.png`
: `blob:vercel.HASH.png`
let clientUrl: string
const expectedPageContent = (count: number) =>
'Hello ' + Array(count).fill(clientUrl).join('+')
beforeAll(() => {
let expectedToken
if (isNextDev || !isTurbopack) {
expectedToken = undefined
} else {
expectedToken = next.assetToken
if (!expectedToken) {
throw new Error('Missing deployment id')
}
}
clientUrl = `/_next/static/media/vercel.HASH.png${expectedToken ? `?dpl=${expectedToken}` : ''}`
})
it('should respond on middleware api', async () => {
const data = await next
.fetch('/middleware')
.then((res) => res.ok && res.text())
const json = JSON.parse(stripVercelPngHash(data))
expect(json).toEqual({
imported: clientUrl,
url: serverEdgeUrl,
})
})
describe('app router', () => {
it('should respond on webmanifest', async () => {
const data = await next
.fetch('/manifest.webmanifest')
.then((res) => res.ok && res.text())
const json = JSON.parse(stripVercelPngHash(data))
expect(json).toEqual({
short_name: 'Next.js',
name: 'Next.js',
icons: [
{
src: clientUrl,
type: 'image/png',
sizes: '512x512',
},
],
// TODO Webpack bug?
description: isTurbopack ? serverFileRegex : clientUrl,
})
})
it('should respond on opengraph-image', async () => {
const data = await next
.fetch('/opengraph-image')
.then((res) => res.ok && res.text())
const json = JSON.parse(stripVercelPngHash(data))
expect(json).toEqual({
imported: clientUrl,
// TODO Webpack bug?
url: isTurbopack ? serverFileRegex : clientUrl,
})
})
for (const page of ['/rsc', '/rsc-edge', '/client', '/client-edge']) {
// TODO Webpack bug?
let shouldSkip = isTurbopack ? false : page.includes('edge')
;(shouldSkip ? it.skip : it)(
`should render the ${page} page`,
async () => {
const $ = await next.render$(page)
// eslint-disable-next-line jest/no-standalone-expect
expect(stripVercelPngHash($('main').text())).toEqual(
expectedPageContent(2)
)
}
)
;(shouldSkip ? it.skip : it)(
`should client-render the ${page} page`,
async () => {
const browser = await next.browser(page)
await retry(async () =>
expect(
stripVercelPngHash(await browser.elementByCss('main').text())
).toEqual(expectedPageContent(2))
)
}
)
}
it('should respond on API', async () => {
const data = await next.fetch('/api').then((res) => res.ok && res.text())
const json = JSON.parse(stripVercelPngHash(data))
expect(json).toEqual({
imported: clientUrl,
// TODO Webpack bug?
url: isTurbopack ? serverFileRegex : clientUrl,
size: isTurbopack ? 30079 : expect.toBeString(),
})
})
})
describe('pages router', () => {
for (const [page, count] of [
['/pages/static', 2],
['/pages/ssr', 3],
['/pages/ssg', 3],
['/pages-edge/static', 2],
['/pages-edge/ssr', 3],
] as const) {
// TODO Webpack bug?
let shouldSkip = isTurbopack ? false : page.includes('edge')
;(shouldSkip ? it.skip : it)(
`should render the ${page} page`,
async () => {
const $ = await next.render$(page)
// eslint-disable-next-line jest/no-standalone-expect
expect(stripVercelPngHash($('main').text())).toEqual(
expectedPageContent(count)
)
}
)
;(shouldSkip ? it.skip : it)(
`should client-render the ${page} page`,
async () => {
const browser = await next.browser(page)
await retry(async () =>
expect(
stripVercelPngHash(await browser.elementByCss('main').text())
).toEqual(expectedPageContent(count))
)
}
)
}
it('should respond on API', async () => {
const data = await next
.fetch('/api/pages/')
.then((res) => res.ok && res.text())
const json = JSON.parse(stripVercelPngHash(data))
expect(json).toEqual({
imported: clientUrl,
url: serverFileRegex,
size: 30079,
})
})
it('should respond on edge API', async () => {
const data = await next
.fetch('/api/pages-edge/')
.then((res) => res.ok && res.text())
const json = JSON.parse(stripVercelPngHash(data))
expect(json).toEqual({
imported: clientUrl,
url: serverEdgeUrl,
})
})
})
})
function stripVercelPngHash(text: string) {
return text.replace(/vercel\.[0-9a-f]{8,}\.png/g, 'vercel.HASH.png')
}