diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index a91050e1b4643..2e9f99ee1e851 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -3,4 +3,7 @@ # https://docs.github.com/en/repositories/working-with-files/using-files/viewing-a-file#ignore-commits-in-the-blame-view # chore(examples): use default prettier for examples/templates (#60530) -4466ba436b996263307171d344cca199e8087744 \ No newline at end of file +4466ba436b996263307171d344cca199e8087744 + +# chore: update prettier to 3.2.5 (#65092) +64b718c6618b6c419872abbf22163ae543ac259e diff --git a/.github/actions/next-integration-stat/src/index.ts b/.github/actions/next-integration-stat/src/index.ts index e4a16f4b66c36..ba7c7eda34438 100644 --- a/.github/actions/next-integration-stat/src/index.ts +++ b/.github/actions/next-integration-stat/src/index.ts @@ -447,29 +447,32 @@ async function getTestResultDiffBase( // Find the latest test result tree, iterate results file names to find out the latest one. // Filename follow ${yyyyMMddHHmm}-${sha}.json format. - const actualTestResultTree = testResultJsonTree.reduce((acc, value) => { - const dateStr = value.path?.split('-')[0].match(/(....)(..)(..)(..)(..)/) + const actualTestResultTree = testResultJsonTree.reduce( + (acc, value) => { + const dateStr = value.path?.split('-')[0].match(/(....)(..)(..)(..)(..)/) - if (!dateStr || dateStr.length < 5) { - return acc - } + if (!dateStr || dateStr.length < 5) { + return acc + } - const date = new Date( - dateStr![1] as any, - (dateStr![2] as any) - 1, - dateStr![3] as any, - dateStr![4] as any, - dateStr![5] as any - ) - if (!acc) { - return { - date, - value, + const date = new Date( + dateStr![1] as any, + (dateStr![2] as any) - 1, + dateStr![3] as any, + dateStr![4] as any, + dateStr![5] as any + ) + if (!acc) { + return { + date, + value, + } } - } - return acc.date >= date ? acc : { date, value } - }, null as any as { date: Date; value: (typeof testResultJsonTree)[0] }) + return acc.date >= date ? acc : { date, value } + }, + null as any as { date: Date; value: (typeof testResultJsonTree)[0] } + ) if (!actualTestResultTree || !actualTestResultTree?.value?.sha) { console.log('There is no test results json stored in the base yet') diff --git a/.github/actions/next-stats-action/src/add-comment.js b/.github/actions/next-stats-action/src/add-comment.js index c65e54236e44d..5001ff558e033 100644 --- a/.github/actions/next-stats-action/src/add-comment.js +++ b/.github/actions/next-stats-action/src/add-comment.js @@ -106,8 +106,8 @@ module.exports = async function addComment( ? '⚠️ ' : '' : change > 0 - ? '⚠️ ' - : '' + ? '⚠️ ' + : '' change = `${warn}${change < 0 ? '-' : '+'}${ useRawValue ? absChange : prettify(absChange, prettyType) }` diff --git a/.github/actions/next-stats-action/src/prepare/load-stats-config.js b/.github/actions/next-stats-action/src/prepare/load-stats-config.js index 55cecb54faad3..54bc3efe6f395 100644 --- a/.github/actions/next-stats-action/src/prepare/load-stats-config.js +++ b/.github/actions/next-stats-action/src/prepare/load-stats-config.js @@ -10,11 +10,9 @@ function loadStatsConfig() { for (const configPath of allowedConfigLocations) { try { relativeStatsAppDir = configPath - statsConfig = require(path.join( - diffRepoDir, - configPath, - 'stats-config.js' - )) + statsConfig = require( + path.join(diffRepoDir, configPath, 'stats-config.js') + ) break } catch (err) { if (err.code !== 'MODULE_NOT_FOUND') { diff --git a/.github/workflows/build_reusable.yml b/.github/workflows/build_reusable.yml index 81a2ffe05f618..6cc1bc92c6c82 100644 --- a/.github/workflows/build_reusable.yml +++ b/.github/workflows/build_reusable.yml @@ -175,7 +175,7 @@ jobs: - run: turbo run get-test-timings -- --build ${{ github.sha }} - run: /bin/bash -c "${{ inputs.afterBuild }}" - timeout-minutes: 15 + timeout-minutes: 30 - name: Upload artifact uses: actions/upload-artifact@v4 diff --git a/.prettierignore b/.prettierignore index a297d08637c34..e89841d37cce1 100644 --- a/.prettierignore +++ b/.prettierignore @@ -4,7 +4,6 @@ _next/ __tmp__/ dist/ -node_modules/ target/ compiled/ @@ -19,6 +18,14 @@ packages/next/src/bundles/webpack/packages/lazy-compilation-*.js packages/next-swc/crates/**/tests/**/output* packages/next-swc/crates/core/tests/loader/issue-32553/input.js +# prettier destroys the directives here +packages/next-swc/crates/next-custom-transforms/tests/errors/react-server-components/client-graph/use-client/input.js +packages/next-swc/crates/next-custom-transforms/tests/errors/react-server-components/server-graph/fake-client-entry/input.js +packages/next-swc/crates/next-custom-transforms/tests/errors/server-actions/server-graph/8/input.js +packages/next-swc/crates/next-custom-transforms/tests/errors/server-actions/server-graph/9/input.js +packages/next-swc/crates/next-custom-transforms/tests/fixture/optimize-barrel/normal/4/input.js +packages/next-swc/crates/next-custom-transforms/tests/fixture/react-server-components/client-graph/client-entry/input.js +packages/next-swc/crates/next-custom-transforms/tests/fixture/react-server-components/server-graph/client-entry/input.js packages/next-swc/native/**/* packages/next-swc/docs/assets/**/* diff --git a/.prettierignore_staged b/.prettierignore_staged deleted file mode 100644 index f1c268594d2f3..0000000000000 --- a/.prettierignore_staged +++ /dev/null @@ -1,17 +0,0 @@ -**/.next/** -**/_next/** -**/dist/** -packages/next-swc/crates/** -packages/next/src/compiled/**/* -packages/next/bundles/webpack/packages/*.runtime.js -lerna.json -packages/next-codemod/transforms/__testfixtures__/**/* -packages/next-codemod/transforms/__tests__/**/* -test/development/basic/hmr/components/parse-error.js -pnpm-lock.yaml -.github/actions/validate-docs-links/lib/index.js -.github/actions/needs-triage/index.js -.github/actions/*/index.mjs -**/convex/_generated/** -test/lib/amp-validator-wasm.js -test/production/pages-dir/production/fixture/amp-validator-wasm.js diff --git a/Cargo.lock b/Cargo.lock index c63d9489c017f..a906a01e6dbab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -321,7 +321,7 @@ dependencies = [ [[package]] name = "auto-hash-map" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "serde", "smallvec", @@ -3061,6 +3061,7 @@ dependencies = [ "fxhash", "getrandom", "iana-time-zone", + "indexmap 1.9.3", "lightningcss-napi", "napi", "napi-build", @@ -3085,7 +3086,7 @@ dependencies = [ [[package]] name = "node-file-trace" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "serde", @@ -6934,7 +6935,7 @@ dependencies = [ [[package]] name = "turbo-tasks" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "async-trait", @@ -6965,7 +6966,7 @@ dependencies = [ [[package]] name = "turbo-tasks-build" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "cargo-lock", @@ -6977,7 +6978,7 @@ dependencies = [ [[package]] name = "turbo-tasks-bytes" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "bytes", @@ -6991,7 +6992,7 @@ dependencies = [ [[package]] name = "turbo-tasks-env" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "dotenvs", @@ -7005,7 +7006,7 @@ dependencies = [ [[package]] name = "turbo-tasks-fetch" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "lazy_static", @@ -7021,7 +7022,7 @@ dependencies = [ [[package]] name = "turbo-tasks-fs" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "auto-hash-map", @@ -7053,7 +7054,7 @@ dependencies = [ [[package]] name = "turbo-tasks-hash" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "base16", "hex", @@ -7065,7 +7066,7 @@ dependencies = [ [[package]] name = "turbo-tasks-macros" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "proc-macro-error", @@ -7078,7 +7079,7 @@ dependencies = [ [[package]] name = "turbo-tasks-macros-shared" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "proc-macro2", "quote", @@ -7088,7 +7089,7 @@ dependencies = [ [[package]] name = "turbo-tasks-malloc" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "mimalloc", ] @@ -7096,12 +7097,13 @@ dependencies = [ [[package]] name = "turbo-tasks-memory" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "auto-hash-map", "concurrent-queue", "dashmap", + "indexmap 1.9.3", "nohash-hasher", "num_cpus", "once_cell", @@ -7121,7 +7123,7 @@ dependencies = [ [[package]] name = "turbopack" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "async-recursion", @@ -7151,7 +7153,7 @@ dependencies = [ [[package]] name = "turbopack-binding" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "auto-hash-map", "mdxjs", @@ -7191,7 +7193,7 @@ dependencies = [ [[package]] name = "turbopack-browser" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "indexmap 1.9.3", @@ -7214,7 +7216,7 @@ dependencies = [ [[package]] name = "turbopack-cli-utils" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "clap", @@ -7231,7 +7233,7 @@ dependencies = [ [[package]] name = "turbopack-core" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "async-recursion", @@ -7260,7 +7262,7 @@ dependencies = [ [[package]] name = "turbopack-css" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "indexmap 1.9.3", @@ -7287,7 +7289,7 @@ dependencies = [ [[package]] name = "turbopack-dev-server" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "async-compression", @@ -7323,7 +7325,7 @@ dependencies = [ [[package]] name = "turbopack-ecmascript" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "async-trait", @@ -7358,7 +7360,7 @@ dependencies = [ [[package]] name = "turbopack-ecmascript-hmr-protocol" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "serde", "serde_json", @@ -7369,7 +7371,7 @@ dependencies = [ [[package]] name = "turbopack-ecmascript-plugins" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "async-trait", @@ -7393,7 +7395,7 @@ dependencies = [ [[package]] name = "turbopack-ecmascript-runtime" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "indoc", @@ -7409,7 +7411,7 @@ dependencies = [ [[package]] name = "turbopack-env" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "indexmap 1.9.3", @@ -7425,7 +7427,7 @@ dependencies = [ [[package]] name = "turbopack-image" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "base64 0.21.4", @@ -7444,7 +7446,7 @@ dependencies = [ [[package]] name = "turbopack-json" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "serde", @@ -7459,7 +7461,7 @@ dependencies = [ [[package]] name = "turbopack-mdx" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "mdxjs", @@ -7474,7 +7476,7 @@ dependencies = [ [[package]] name = "turbopack-node" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "async-stream", @@ -7508,7 +7510,7 @@ dependencies = [ [[package]] name = "turbopack-nodejs" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "indexmap 1.9.3", @@ -7528,7 +7530,7 @@ dependencies = [ [[package]] name = "turbopack-resolve" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "indexmap 1.9.3", @@ -7546,7 +7548,7 @@ dependencies = [ [[package]] name = "turbopack-static" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "serde", @@ -7562,7 +7564,7 @@ dependencies = [ [[package]] name = "turbopack-swc-utils" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "swc_core", "turbo-tasks", @@ -7573,7 +7575,7 @@ dependencies = [ [[package]] name = "turbopack-trace-utils" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "crossbeam-channel", @@ -7589,7 +7591,7 @@ dependencies = [ [[package]] name = "turbopack-wasm" version = "0.1.0" -source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240503.1#844f4d6ce023536e0e18abe74348228dcc4c7b75" +source = "git+https://github.com/vercel/turbo.git?tag=turbopack-240508.4#adfb5990c9c65e831d8c064337f25d96bf51d1a8" dependencies = [ "anyhow", "indexmap 1.9.3", @@ -8599,7 +8601,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.0", + "windows-targets 0.52.5", ] [[package]] @@ -8634,17 +8636,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" +checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ - "windows_aarch64_gnullvm 0.52.0", - "windows_aarch64_msvc 0.52.0", - "windows_i686_gnu 0.52.0", - "windows_i686_msvc 0.52.0", - "windows_x86_64_gnu 0.52.0", - "windows_x86_64_gnullvm 0.52.0", - "windows_x86_64_msvc 0.52.0", + "windows_aarch64_gnullvm 0.52.5", + "windows_aarch64_msvc 0.52.5", + "windows_i686_gnu 0.52.5", + "windows_i686_gnullvm", + "windows_i686_msvc 0.52.5", + "windows_x86_64_gnu 0.52.5", + "windows_x86_64_gnullvm 0.52.5", + "windows_x86_64_msvc 0.52.5", ] [[package]] @@ -8661,9 +8664,9 @@ checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" +checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" @@ -8685,9 +8688,9 @@ checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" [[package]] name = "windows_aarch64_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" +checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" @@ -8709,9 +8712,15 @@ checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" [[package]] name = "windows_i686_gnu" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" +checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" @@ -8733,9 +8742,9 @@ checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" [[package]] name = "windows_i686_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" +checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" @@ -8757,9 +8766,9 @@ checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" [[package]] name = "windows_x86_64_gnu" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" +checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" @@ -8775,9 +8784,9 @@ checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" +checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" @@ -8799,9 +8808,9 @@ checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" [[package]] name = "windows_x86_64_msvc" -version = "0.52.0" +version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" +checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" diff --git a/Cargo.toml b/Cargo.toml index ef155c30092b7..75ef82b9b137c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,11 +37,11 @@ swc_core = { version = "0.90.33", features = [ testing = { version = "0.35.22" } # Turbo crates -turbopack-binding = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-240503.1" } +turbopack-binding = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-240508.4" } # [TODO]: need to refactor embed_directory! macro usages, as well as resolving turbo_tasks::function, macros.. -turbo-tasks = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-240503.1" } +turbo-tasks = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-240508.4" } # [TODO]: need to refactor embed_directory! macro usage in next-core -turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-240503.1" } +turbo-tasks-fs = { git = "https://github.com/vercel/turbo.git", tag = "turbopack-240508.4" } # General Deps diff --git a/bench/next-minimal-server/bin/minimal-server.js b/bench/next-minimal-server/bin/minimal-server.js index 44861262aee06..332e53d0b727e 100755 --- a/bench/next-minimal-server/bin/minimal-server.js +++ b/bench/next-minimal-server/bin/minimal-server.js @@ -10,11 +10,9 @@ const path = require('path') const appDir = process.cwd() const distDir = '.next' -const compiledConfig = require(path.join( - appDir, - distDir, - 'required-server-files.json' -)).config +const compiledConfig = require( + path.join(appDir, distDir, 'required-server-files.json') +).config process.chdir(appDir) diff --git a/docs/02-app/01-building-your-application/02-data-fetching/02-server-actions-and-mutations.mdx b/docs/02-app/01-building-your-application/02-data-fetching/02-server-actions-and-mutations.mdx index 9284955029dde..65105fcc1e919 100644 --- a/docs/02-app/01-building-your-application/02-data-fetching/02-server-actions-and-mutations.mdx +++ b/docs/02-app/01-building-your-application/02-data-fetching/02-server-actions-and-mutations.mdx @@ -358,10 +358,10 @@ export default async function createsUser(formData) { } ``` -Once the fields have been validated on the server, you can return a serializable object in your action and use the React [`useFormState`](https://react.dev/reference/react-dom/hooks/useFormState) hook to show a message to the user. +Once the fields have been validated on the server, you can return a serializable object in your action and use the React [`useActionState`](https://react.dev/reference/react/useActionState) hook to show a message to the user. -- By passing the action to `useFormState`, the action's function signature changes to receive a new `prevState` or `initialState` parameter as its first argument. -- `useFormState` is a React hook and therefore must be used in a Client Component. +- By passing the action to `useActionState`, the action's function signature changes to receive a new `prevState` or `initialState` parameter as its first argument. +- `useActionState` is a React hook and therefore must be used in a Client Component. ```tsx filename="app/actions.ts" switcher 'use server' @@ -385,12 +385,12 @@ export async function createUser(prevState, formData) { } ``` -Then, you can pass your action to the `useFormState` hook and use the returned `state` to display an error message. +Then, you can pass your action to the `useActionState` hook and use the returned `state` to display an error message. ```tsx filename="app/ui/signup.tsx" switcher 'use client' -import { useFormState } from 'react-dom' +import { useActionState } from 'react' import { createUser } from '@/app/actions' const initialState = { @@ -398,7 +398,7 @@ const initialState = { } export function Signup() { - const [state, formAction] = useFormState(createUser, initialState) + const [state, formAction] = useActionState(createUser, initialState) return (
@@ -417,7 +417,7 @@ export function Signup() { ```jsx filename="app/ui/signup.js" switcher 'use client' -import { useFormState } from 'react-dom' +import { useActionState } from 'react' import { createUser } from '@/app/actions' const initialState = { @@ -425,7 +425,7 @@ const initialState = { } export function Signup() { - const [state, formAction] = useFormState(createUser, initialState) + const [state, formAction] = useActionState(createUser, initialState) return ( @@ -739,7 +739,7 @@ export async function createTodo(prevState, formData) { > **Good to know:** > -> - Aside from throwing the error, you can also return an object to be handled by `useFormState`. See [Server-side validation and error handling](#server-side-validation-and-error-handling). +> - Aside from throwing the error, you can also return an object to be handled by `useActionState`. See [Server-side validation and error handling](#server-side-validation-and-error-handling). ### Revalidating data @@ -1002,5 +1002,5 @@ For more information on Server Actions, check out the following React docs: - [`"use server"`](https://react.dev/reference/react/use-server) - [``](https://react.dev/reference/react-dom/components/form) - [`useFormStatus`](https://react.dev/reference/react-dom/hooks/useFormStatus) -- [`useFormState`](https://react.dev/reference/react-dom/hooks/useFormState) +- [`useActionState`](https://react.dev/reference/react/useActionState) - [`useOptimistic`](https://react.dev/reference/react/useOptimistic) diff --git a/docs/02-app/01-building-your-application/04-caching/index.mdx b/docs/02-app/01-building-your-application/04-caching/index.mdx index 3d68b46d0f0c3..a3975e8ca9fcb 100644 --- a/docs/02-app/01-building-your-application/04-caching/index.mdx +++ b/docs/02-app/01-building-your-application/04-caching/index.mdx @@ -369,7 +369,7 @@ The cache is stored in the browser's temporary memory. Two factors determine how While a page refresh will clear **all** cached segments, the automatic invalidation period only affects the individual segment from the time it was prefetched. -> **Note**: There is [experimental support](/docs/app/api-reference/next-config-js/staleTimes) for configuring these values as of This configuration option is available as of [v14.2.0](https://github.com/vercel/next.js/releases/tag/v14.2.0). +> **Note**: There is [experimental support](/docs/app/api-reference/next-config-js/staleTimes) for configuring these values, available as of [v14.2.0](https://github.com/vercel/next.js/releases/tag/v14.2.0). ### Invalidation diff --git a/docs/02-app/01-building-your-application/07-configuring/03-environment-variables.mdx b/docs/02-app/01-building-your-application/07-configuring/03-environment-variables.mdx index b36edd1b0a070..7876459c3979d 100644 --- a/docs/02-app/01-building-your-application/07-configuring/03-environment-variables.mdx +++ b/docs/02-app/01-building-your-application/07-configuring/03-environment-variables.mdx @@ -14,14 +14,14 @@ description: Learn to add and access environment variables in your Next.js appli Next.js comes with built-in support for environment variables, which allows you to do the following: -- [Use `.env.local` to load environment variables](#loading-environment-variables) +- [Use `.env` to load environment variables](#loading-environment-variables) - [Bundle environment variables for the browser by prefixing with `NEXT_PUBLIC_`](#bundling-environment-variables-for-the-browser) ## Loading Environment Variables -Next.js has built-in support for loading environment variables from `.env.local` into `process.env`. +Next.js has built-in support for loading environment variables from `.env*` files into `process.env`. -```txt filename=".env.local" +```txt filename=".env" DB_HOST=localhost DB_USER=myuser DB_PASS=mypassword @@ -51,7 +51,7 @@ export async function getStaticProps() { > **Note**: Next.js also supports multiline variables inside of your `.env*` files: > > ```bash -> # .env.local +> # .env > > # you can write with line breaks > PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY----- @@ -211,13 +211,11 @@ export default function Component() { ## Default Environment Variables -In general only one `.env.local` file is needed. However, sometimes you might want to add some defaults for the `development` (`next dev`) or `production` (`next start`) environment. +Typically, only `.env*` file is needed. However, sometimes you might want to add some defaults for the `development` (`next dev`) or `production` (`next start`) environment. Next.js allows you to set defaults in `.env` (all environments), `.env.development` (development environment), and `.env.production` (production environment). -`.env.local` always overrides the defaults set. - -> **Good to know**: `.env`, `.env.development`, and `.env.production` files should be included in your repository as they define defaults. **`.env*.local` should be added to `.gitignore`**, as those files are intended to be ignored. `.env.local` is where secrets can be stored. +> **Good to know**: `.env`, `.env.development`, and `.env.production` files should be included in your repository as they define defaults. All `.env` files are excluded in `.gitignore` by default, allowing you to opt-into committing these values to your repository. ## Environment Variables on Vercel @@ -228,7 +226,7 @@ All types of Environment Variables should be configured there. Even Environment If you've configured [Development Environment Variables](https://vercel.com/docs/concepts/projects/environment-variables#development-environment-variables?utm_source=next-site&utm_medium=docs&utm_campaign=next-website) you can pull them into a `.env.local` for usage on your local machine using the following command: ```bash filename="Terminal" -vercel env pull .env.local +vercel env pull ``` > **Good to know**: When deploying your Next.js application to [Vercel](https://vercel.com), your environment variables in `.env*` files will not be made available to Edge Runtime, unless their name are prefixed with `NEXT_PUBLIC_`. We strongly recommend managing your environment variables in [Project Settings](https://vercel.com/docs/projects/environment-variables?utm_medium=docs&utm_source=next-site&utm_campaign=next-website) instead, from where all environment variables are available. diff --git a/docs/02-app/01-building-your-application/09-authentication/index.mdx b/docs/02-app/01-building-your-application/09-authentication/index.mdx index 36934af91ae42..7fcad132dfa48 100644 --- a/docs/02-app/01-building-your-application/09-authentication/index.mdx +++ b/docs/02-app/01-building-your-application/09-authentication/index.mdx @@ -29,7 +29,7 @@ The examples on this page walk through basic username and password auth for educ ### Sign-up and login functionality -You can use the [``](https://react.dev/reference/react-dom/components/form) element with React's [Server Actions](/docs/app/building-your-application/rendering/server-components), [`useFormStatus()`](https://react.dev/reference/react-dom/hooks/useFormStatus), and [`useFormState()`](https://react.dev/reference/react-dom/hooks/useFormState) to capture user credentials, validate form fields, and call your Authentication Provider's API or database. +You can use the [``](https://react.dev/reference/react-dom/components/form) element with React's [Server Actions](/docs/app/building-your-application/data-fetching/server-actions-and-mutations), [`useFormStatus()`](https://react.dev/reference/react-dom/hooks/useFormStatus), and [`useActionState()`](https://react.dev/reference/react/useActionState) to capture user credentials, validate form fields, and call your Authentication Provider's API or database. Since Server Actions always execute on the server, they provide a secure environment for handling authentication logic. @@ -200,16 +200,16 @@ export async function signup(state, formData) { } ``` -Back in your ``, you can use React's `useFormState()` hook to display validation errors to the user: +Back in your ``, you can use React's `useActionState()` hook to display validation errors to the user: ```tsx filename="app/ui/signup-form.tsx" switcher highlight={7,15,21,27-36} 'use client' -import { useFormState } from 'react-dom' +import { useActionState } from 'react' import { signup } from '@/app/actions/auth' export function SignupForm() { - const [state, action] = useFormState(signup, undefined) + const [state, action] = useActionState(signup, undefined) return ( @@ -248,11 +248,11 @@ export function SignupForm() { ```jsx filename="app/ui/signup-form.js" switcher highlight={7,15,21,27-36} 'use client' -import { useFormState } from 'react-dom' +import { useActionState } from 'react' import { signup } from '@/app/actions/auth' export function SignupForm() { - const [state, action] = useFormState(signup, undefined) + const [state, action] = useActionState(signup, undefined) return ( @@ -293,7 +293,8 @@ You can also use the `useFormStatus()` hook to handle the pending state on form ```tsx filename="app/ui/signup-form.tsx" highlight={6} switcher 'use client' -import { useFormStatus, useFormState } from 'react-dom' +import { useActionState } from 'react' +import { useFormStatus } from 'react-dom' export function SignupButton() { const { pending } = useFormStatus() @@ -309,7 +310,8 @@ export function SignupButton() { ```jsx filename="app/ui/signup-form.js" highlight={6} switcher 'use client' -import { useFormStatus, useFormState } from 'react-dom' +import { useActionState } from 'react' +import { useFormStatus } from 'react-dom' export function SignupButton() { const { pending } = useFormStatus() diff --git a/docs/02-app/01-building-your-application/11-upgrading/05-from-create-react-app.mdx b/docs/02-app/01-building-your-application/11-upgrading/05-from-create-react-app.mdx index ecb915de8a35a..7bab3db2ce293 100644 --- a/docs/02-app/01-building-your-application/11-upgrading/05-from-create-react-app.mdx +++ b/docs/02-app/01-building-your-application/11-upgrading/05-from-create-react-app.mdx @@ -152,7 +152,7 @@ export default function RootLayout({ return ( - + React App diff --git a/docs/02-app/02-api-reference/02-file-conventions/01-metadata/sitemap.mdx b/docs/02-app/02-api-reference/02-file-conventions/01-metadata/sitemap.mdx index 20cccf47e98e3..2e8469433d0ac 100644 --- a/docs/02-app/02-api-reference/02-file-conventions/01-metadata/sitemap.mdx +++ b/docs/02-app/02-api-reference/02-file-conventions/01-metadata/sitemap.mdx @@ -262,9 +262,7 @@ export default async function sitemap({ id }) { } ``` -In production, your generated sitemaps will be available at `/.../sitemap/[id].xml`. For example, `/product/sitemap/1.xml`. - -In development, you can view the generated sitemap on `/.../sitemap.xml/[id]`. For example, `/product/sitemap.xml/1`. This difference is temporary and will follow the production format. +Your generated sitemaps will be available at `/.../sitemap/[id]`. For example, `/product/sitemap/1`. See the [`generateSitemaps` API reference](/docs/app/api-reference/functions/generate-sitemaps) for more information. diff --git a/docs/02-app/02-api-reference/04-functions/generate-metadata.mdx b/docs/02-app/02-api-reference/04-functions/generate-metadata.mdx index 9884bdc3f7b8e..2a0e10e3713c6 100644 --- a/docs/02-app/02-api-reference/04-functions/generate-metadata.mdx +++ b/docs/02-app/02-api-reference/04-functions/generate-metadata.mdx @@ -428,10 +428,16 @@ export const metadata = { #### Default value -If not configured, `metadataBase` has a **default value** +If not configured, `metadataBase` has a **default value**. -- When [`VERCEL_URL`](https://vercel.com/docs/concepts/projects/environment-variables/system-environment-variables#:~:text=.-,VERCEL_URL,-The%20domain%20name) is detected: `https://${process.env.VERCEL_URL}` otherwise it falls back to `http://localhost:${process.env.PORT || 3000}`. -- When overriding the default, we recommend using environment variables to compute the URL. This allows configuring a URL for local development, staging, and production environments. +> On Vercel: +> +> - For production deployments, `VERCEL_PROJECT_PRODUCTION_URL` will be used. +> - For preview deployments, `VERCEL_BRANCH_URL` will take priority, and fallback to `VERCEL_URL` if it's not present. +> +> If these values are present they will be used as the **default value** of `metadataBase`, otherwise it falls back to `http://localhost:${process.env.PORT || 3000}`. This allows Open Graph images to work on both local build and Vercel preview and production deployments. When overriding the default, we recommend using environment variables to compute the URL. This allows configuring a URL for local development, staging, and production environments. +> +> See more details about these environment variables in the [System Environment Variables](https://vercel.com/docs/concepts/projects/environment-variables/system-environment-variables) docs. #### URL Composition diff --git a/docs/02-app/02-api-reference/04-functions/revalidatePath.mdx b/docs/02-app/02-api-reference/04-functions/revalidatePath.mdx index 488cb48be06a0..7d23b8d8e3d13 100644 --- a/docs/02-app/02-api-reference/04-functions/revalidatePath.mdx +++ b/docs/02-app/02-api-reference/04-functions/revalidatePath.mdx @@ -19,7 +19,7 @@ revalidatePath(path: string, type?: 'page' | 'layout'): void; ``` - `path`: Either a string representing the filesystem path associated with the data you want to revalidate (for example, `/product/[slug]/page`), or the literal route segment (for example, `/product/123`). Must be less than 1024 characters. This value is case-sensitive. -- `type`: (optional) `'page'` or `'layout'` string to change the type of path to revalidate. If `path` contains a dynamic segment (for example, `/product/[slug]/page`), this parameter is required. +- `type`: (optional) `'page'` or `'layout'` string to change the type of path to revalidate. If `path` contains a dynamic segment (for example, `/product/[slug]/page`), this parameter is required. If path refers to the literal route segment, e.g., `/product/1` for a dynamic page (e.g., `/product/[slug]/page`), you should not provide `type`. ## Returns diff --git a/docs/02-app/02-api-reference/05-next-config-js/serverComponentsExternalPackages.mdx b/docs/02-app/02-api-reference/05-next-config-js/serverExternalPackages.mdx similarity index 93% rename from docs/02-app/02-api-reference/05-next-config-js/serverComponentsExternalPackages.mdx rename to docs/02-app/02-api-reference/05-next-config-js/serverExternalPackages.mdx index 69526e96f1edf..620fdf3a4b1f0 100644 --- a/docs/02-app/02-api-reference/05-next-config-js/serverComponentsExternalPackages.mdx +++ b/docs/02-app/02-api-reference/05-next-config-js/serverExternalPackages.mdx @@ -1,5 +1,5 @@ --- -title: serverComponentsExternalPackages +title: serverExternalPackages description: Opt-out specific dependencies from the Server Components bundling and use native Node.js `require`. --- @@ -10,9 +10,7 @@ If a dependency is using Node.js specific features, you can choose to opt-out sp ```js filename="next.config.js" /** @type {import('next').NextConfig} */ const nextConfig = { - experimental: { - serverComponentsExternalPackages: ['@acme/ui'], - }, + serverExternalPackages: ['@acme/ui'], } module.exports = nextConfig diff --git a/docs/02-app/02-api-reference/06-create-next-app.mdx b/docs/02-app/02-api-reference/06-create-next-app.mdx index 069b2e2d858f8..7590067d62c2d 100644 --- a/docs/02-app/02-api-reference/06-create-next-app.mdx +++ b/docs/02-app/02-api-reference/06-create-next-app.mdx @@ -84,6 +84,10 @@ Options: Specify import alias to use (default "@/*"). + --empty + + Initialize an empty project. + --use-npm Explicitly tell the CLI to bootstrap the app using npm diff --git a/docs/03-pages/02-api-reference/03-next-config-js/bundlePagesRouterDependencies.mdx b/docs/03-pages/02-api-reference/03-next-config-js/bundlePagesRouterDependencies.mdx new file mode 100644 index 0000000000000..9643981dba694 --- /dev/null +++ b/docs/03-pages/02-api-reference/03-next-config-js/bundlePagesRouterDependencies.mdx @@ -0,0 +1,17 @@ +--- +title: bundlePagesRouterDependencies +description: Enable automatic dependency bundling for Pages Router +--- + +Enable automatic server-side dependency bundling for Pages Router applications. Matches the automatic dependency bundling in App Router. + +```js filename="next.config.js" +/** @type {import('next').NextConfig} */ +const nextConfig = { + bundlePagesRouterDependencies: true, +} + +module.exports = nextConfig +``` + +Explicitly opt-out certain packages from being bundled using the [`serverExternalPackages`](/docs/pages/api-reference/next-config-js/serverExternalPackages) option. diff --git a/docs/03-pages/02-api-reference/03-next-config-js/serverExternalPackages.mdx b/docs/03-pages/02-api-reference/03-next-config-js/serverExternalPackages.mdx new file mode 100644 index 0000000000000..b83d8fc1daeee --- /dev/null +++ b/docs/03-pages/02-api-reference/03-next-config-js/serverExternalPackages.mdx @@ -0,0 +1,77 @@ +--- +title: serverExternalPackages +description: Opt-out specific dependencies from the dependency bundling enabled by `bundlePagesRouterDependencies`. +--- + +Opt-out specific dependencies from being included in the automatic bundling of the [`bundlePagesRouterDependencies`](/docs/pages/api-reference/next-config-js/bundlePagesRouterDependencies) option. + +These pages will then use native Node.js `require` to resolve the dependency. + +```js filename="next.config.js" +/** @type {import('next').NextConfig} */ +const nextConfig = { + serverExternalPackages: ['@acme/ui'], +} + +module.exports = nextConfig +``` + +Next.js includes a [short list of popular packages](https://github.com/vercel/next.js/blob/canary/packages/next/src/lib/server-external-packages.json) that currently are working on compatibility and automatically opt-ed out: + +- `@appsignal/nodejs` +- `@aws-sdk/client-s3` +- `@aws-sdk/s3-presigned-post` +- `@blockfrost/blockfrost-js` +- `@highlight-run/node` +- `@jpg-store/lucid-cardano` +- `@libsql/client` +- `@mikro-orm/core` +- `@mikro-orm/knex` +- `@node-rs/argon2` +- `@node-rs/bcrypt` +- `@prisma/client` +- `@react-pdf/renderer` +- `@sentry/profiling-node` +- `@swc/core` +- `argon2` +- `autoprefixer` +- `aws-crt` +- `bcrypt` +- `better-sqlite3` +- `canvas` +- `cpu-features` +- `cypress` +- `eslint` +- `express` +- `firebase-admin` +- `isolated-vm` +- `jest` +- `jsdom` +- `libsql` +- `mdx-bundler` +- `mongodb` +- `mongoose` +- `next-mdx-remote` +- `next-seo` +- `node-pty` +- `node-web-audio-api` +- `oslo` +- `pg` +- `playwright` +- `postcss` +- `prettier` +- `prisma` +- `puppeteer-core` +- `puppeteer` +- `rimraf` +- `sharp` +- `shiki` +- `sqlite3` +- `tailwindcss` +- `ts-node` +- `typescript` +- `vscode-oniguruma` +- `undici` +- `webpack` +- `websocket` +- `zeromq` diff --git a/examples/app-dir-mdx/app/page.module.css b/examples/app-dir-mdx/app/page.module.css index 87f36d6d8565b..2182ce1cacb40 100644 --- a/examples/app-dir-mdx/app/page.module.css +++ b/examples/app-dir-mdx/app/page.module.css @@ -51,7 +51,9 @@ border-radius: var(--border-radius); background: rgba(var(--card-rgb), 0); border: 1px solid rgba(var(--card-border-rgb), 0); - transition: background 200ms, border 200ms; + transition: + background 200ms, + border 200ms; } .card span { diff --git a/examples/basic-css/styles.module.css b/examples/basic-css/styles.module.css index b841ef4cfaddb..7c8b0abdf8371 100644 --- a/examples/basic-css/styles.module.css +++ b/examples/basic-css/styles.module.css @@ -1,5 +1,8 @@ .hello { - font: 15px Helvetica, Arial, sans-serif; + font: + 15px Helvetica, + Arial, + sans-serif; background: #eee; padding: 100px; text-align: center; diff --git a/examples/blog/styles/main.css b/examples/blog/styles/main.css index 326b847a94042..b12ceb0ba74f3 100644 --- a/examples/blog/styles/main.css +++ b/examples/blog/styles/main.css @@ -15,12 +15,30 @@ } body { - font-family: "Inter var", system-ui, -apple-system, BlinkMacSystemFont, - "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, - "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-family: + "Inter var", + system-ui, + -apple-system, + BlinkMacSystemFont, + "Segoe UI", + Roboto, + "Helvetica Neue", + Arial, + "Noto Sans", + sans-serif, + "Apple Color Emoji", + "Segoe UI Emoji", + "Segoe UI Symbol", + "Noto Color Emoji"; -webkit-font-smoothing: subpixel-antialiased; - font-feature-settings: "case" 1, "cpsp" 1, "dlig" 1, "cv01" 1, "cv02", - "cv03" 1, "cv04" 1; + font-feature-settings: + "case" 1, + "cpsp" 1, + "dlig" 1, + "cv01" 1, + "cv02", + "cv03" 1, + "cv04" 1; font-variation-settings: "wght" 450; font-variant: common-ligatures contextual; letter-spacing: -0.02em; diff --git a/examples/cms-buttercms/css/lineicons.css b/examples/cms-buttercms/css/lineicons.css index 6ec975873914b..92267341185bc 100644 --- a/examples/cms-buttercms/css/lineicons.css +++ b/examples/cms-buttercms/css/lineicons.css @@ -7,7 +7,8 @@ Author: lineicons.com @font-face { font-family: "LineIcons"; src: url("fonts/LineIcons.eot"); - src: url("fonts/LineIcons.eot") format("embedded-opentype"), + src: + url("fonts/LineIcons.eot") format("embedded-opentype"), url("fonts/LineIcons.woff2") format("woff2"), url("fonts/LineIcons.woff") format("woff"), url("fonts/LineIcons.ttf") format("truetype"), diff --git a/examples/cms-buttercms/css/tiny-slider.min.css b/examples/cms-buttercms/css/tiny-slider.min.css index 89689dde2b99e..d1c1047edbb82 100644 --- a/examples/cms-buttercms/css/tiny-slider.min.css +++ b/examples/cms-buttercms/css/tiny-slider.min.css @@ -49,9 +49,15 @@ .tns-gallery > .tns-item { position: absolute; left: -100%; - -webkit-transition: transform 0s, opacity 0s; - -moz-transition: transform 0s, opacity 0s; - transition: transform 0s, opacity 0s; + -webkit-transition: + transform 0s, + opacity 0s; + -moz-transition: + transform 0s, + opacity 0s; + transition: + transform 0s, + opacity 0s; } .tns-gallery > .tns-slide-active { position: relative; diff --git a/examples/cms-contentful/lib/api.ts b/examples/cms-contentful/lib/api.ts index 9c4249c319dbe..4983a8c191bea 100644 --- a/examples/cms-contentful/lib/api.ts +++ b/examples/cms-contentful/lib/api.ts @@ -92,8 +92,8 @@ export async function getPostAndMorePosts( const entry = await fetchGraphQL( `query { postCollection(where: { slug: "${slug}" }, preview: ${ - preview ? "true" : "false" - }, limit: 1) { + preview ? "true" : "false" + }, limit: 1) { items { ${POST_GRAPHQL_FIELDS} } @@ -104,8 +104,8 @@ export async function getPostAndMorePosts( const entries = await fetchGraphQL( `query { postCollection(where: { slug_not_in: "${slug}" }, order: date_DESC, preview: ${ - preview ? "true" : "false" - }, limit: 2) { + preview ? "true" : "false" + }, limit: 2) { items { ${POST_GRAPHQL_FIELDS} } diff --git a/examples/cms-kontent-ai/pages/posts/[slug].tsx b/examples/cms-kontent-ai/pages/posts/[slug].tsx index 81f100b4ad00d..cf7452731a2fb 100644 --- a/examples/cms-kontent-ai/pages/posts/[slug].tsx +++ b/examples/cms-kontent-ai/pages/posts/[slug].tsx @@ -89,7 +89,7 @@ export async function getStaticPaths() { params: { slug, }, - } || []), + }) || [], ), fallback: false, }; diff --git a/examples/cms-plasmic/pages/[[...catchall]].tsx b/examples/cms-plasmic/pages/[[...catchall]].tsx index 081359a7a8944..601dd525c4e29 100644 --- a/examples/cms-plasmic/pages/[[...catchall]].tsx +++ b/examples/cms-plasmic/pages/[[...catchall]].tsx @@ -32,8 +32,8 @@ export const getStaticProps: GetStaticProps = async (context) => { typeof catchall === "string" ? catchall : Array.isArray(catchall) - ? `/${catchall.join("/")}` - : "/"; + ? `/${catchall.join("/")}` + : "/"; const plasmicData = await PLASMIC.maybeFetchComponentData(plasmicPath); if (!plasmicData) { // This is some non-Plasmic catch-all page diff --git a/examples/cms-plasmic/styles/globals.css b/examples/cms-plasmic/styles/globals.css index e5e2dcc23baf1..51a2a4eaacd86 100644 --- a/examples/cms-plasmic/styles/globals.css +++ b/examples/cms-plasmic/styles/globals.css @@ -2,8 +2,18 @@ html, body { padding: 0; margin: 0; - font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, - Ubuntu, Cantarell, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; + font-family: + -apple-system, + BlinkMacSystemFont, + Segoe UI, + Roboto, + Oxygen, + Ubuntu, + Cantarell, + Fira Sans, + Droid Sans, + Helvetica Neue, + sans-serif; } a { diff --git a/examples/cms-sitecore-xmcloud/src/assets/sass/base/typehead/_typehead.scss b/examples/cms-sitecore-xmcloud/src/assets/sass/base/typehead/_typehead.scss index 32bc1aaaae49e..eca0feb45233f 100644 --- a/examples/cms-sitecore-xmcloud/src/assets/sass/base/typehead/_typehead.scss +++ b/examples/cms-sitecore-xmcloud/src/assets/sass/base/typehead/_typehead.scss @@ -22,7 +22,9 @@ border: 1px solid $tt-dropdown-border; max-height: 300px; overflow-y: auto; - box-shadow: 0 3px 8px 0 rgba(0, 0, 0, 0.2), 0 0 0 1px rgba(0, 0, 0, 0.08); + box-shadow: + 0 3px 8px 0 rgba(0, 0, 0, 0.2), + 0 0 0 1px rgba(0, 0, 0, 0.08); } .tt-suggestion { padding: 4px 10px; diff --git a/examples/cms-sitecore-xmcloud/src/lib/page-props-factory/index.ts b/examples/cms-sitecore-xmcloud/src/lib/page-props-factory/index.ts index 292d54702ac8c..3733970c00b1d 100644 --- a/examples/cms-sitecore-xmcloud/src/lib/page-props-factory/index.ts +++ b/examples/cms-sitecore-xmcloud/src/lib/page-props-factory/index.ts @@ -37,11 +37,14 @@ export class SitecorePagePropsFactory { ): Promise { const extendedProps = await (Object.values(plugins) as Plugin[]) .sort((p1, p2) => p1.order - p2.order) - .reduce(async (result, plugin) => { - const props = await result; - const newProps = await plugin.exec(props, context); - return newProps; - }, Promise.resolve({} as SitecorePageProps)); + .reduce( + async (result, plugin) => { + const props = await result; + const newProps = await plugin.exec(props, context); + return newProps; + }, + Promise.resolve({} as SitecorePageProps), + ); return extendedProps; } diff --git a/examples/cms-wordpress/lib/api.ts b/examples/cms-wordpress/lib/api.ts index c42d8c5ed782a..2d77b5f3bcb4f 100644 --- a/examples/cms-wordpress/lib/api.ts +++ b/examples/cms-wordpress/lib/api.ts @@ -4,9 +4,8 @@ async function fetchAPI(query = "", { variables }: Record = {}) { const headers = { "Content-Type": "application/json" }; if (process.env.WORDPRESS_AUTH_REFRESH_TOKEN) { - headers[ - "Authorization" - ] = `Bearer ${process.env.WORDPRESS_AUTH_REFRESH_TOKEN}`; + headers["Authorization"] = + `Bearer ${process.env.WORDPRESS_AUTH_REFRESH_TOKEN}`; } // WPGraphQL Plugin must be enabled diff --git a/examples/markdoc/public/globals.css b/examples/markdoc/public/globals.css index d97aabc5a0042..ed5a46bd05606 100644 --- a/examples/markdoc/public/globals.css +++ b/examples/markdoc/public/globals.css @@ -1,7 +1,19 @@ body { - font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, - "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, - "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + font-family: + ui-sans-serif, + system-ui, + -apple-system, + BlinkMacSystemFont, + "Segoe UI", + Roboto, + "Helvetica Neue", + Arial, + "Noto Sans", + sans-serif, + "Apple Color Emoji", + "Segoe UI Emoji", + "Segoe UI Symbol", + "Noto Color Emoji"; color: rgba(60, 66, 87, 1); margin: 0; } diff --git a/examples/nested-components/components/paragraph.tsx b/examples/nested-components/components/paragraph.tsx index f92085a6f121f..815587f4bfb6c 100644 --- a/examples/nested-components/components/paragraph.tsx +++ b/examples/nested-components/components/paragraph.tsx @@ -8,7 +8,9 @@ export default function Paragraph({ children }: ParagraphProps) { {children} diff --git a/examples/nested-components/components/post.tsx b/examples/nested-components/components/post.tsx index 7a4388408cc7f..7e93d63ba95d3 100644 --- a/examples/nested-components/components/post.tsx +++ b/examples/nested-components/components/post.tsx @@ -10,7 +10,9 @@ export default function Post({ title, children }: PostProps) { {children} "); + currentlyRenderingBoundaryHasStylesToHoist = !0; + rules.length = 0; + hrefs.length = 0; } - - target.push(endOfStartTag); - pushInnerHTML(target, innerHTML, children); - return children; } - -function flattenOptionChildren(children) { - let content = ''; // Flatten children and warn if they aren't strings or numbers; - // invalid types are ignored. - - React.Children.forEach(children, function (child) { - if (child == null) { - return; - } - - content += child; +function hasStylesToHoist(stylesheet) { + return 2 !== stylesheet.state + ? (currentlyRenderingBoundaryHasStylesToHoist = !0) + : !1; +} +function writeHoistablesForBoundary(destination, hoistableState, renderState) { + currentlyRenderingBoundaryHasStylesToHoist = !1; + destinationHasCapacity = !0; + hoistableState.styles.forEach(flushStyleTagsLateForBoundary, destination); + hoistableState.stylesheets.forEach(hasStylesToHoist); + currentlyRenderingBoundaryHasStylesToHoist && + (renderState.stylesToHoist = !0); + return destinationHasCapacity; +} +function flushResource(resource) { + for (var i = 0; i < resource.length; i++) this.push(resource[i]); + resource.length = 0; +} +var stylesheetFlushingQueue = []; +function flushStyleInPreamble(stylesheet) { + pushLinkImpl(stylesheetFlushingQueue, stylesheet.props); + for (var i = 0; i < stylesheetFlushingQueue.length; i++) + this.push(stylesheetFlushingQueue[i]); + stylesheetFlushingQueue.length = 0; + stylesheet.state = 2; +} +function flushStylesInPreamble(styleQueue) { + var hasStylesheets = 0 < styleQueue.sheets.size; + styleQueue.sheets.forEach(flushStyleInPreamble, this); + styleQueue.sheets.clear(); + var rules = styleQueue.rules, + hrefs = styleQueue.hrefs; + if (!hasStylesheets || hrefs.length) { + this.push('"); + rules.length = 0; + hrefs.length = 0; + } +} +function preloadLateStyle(stylesheet) { + if (0 === stylesheet.state) { + stylesheet.state = 1; + var props = stylesheet.props; + pushLinkImpl(stylesheetFlushingQueue, { + rel: "preload", + as: "style", + href: stylesheet.props.href, + crossOrigin: props.crossOrigin, + fetchPriority: props.fetchPriority, + integrity: props.integrity, + media: props.media, + hrefLang: props.hrefLang, + referrerPolicy: props.referrerPolicy + }); + for ( + stylesheet = 0; + stylesheet < stylesheetFlushingQueue.length; + stylesheet++ + ) + this.push(stylesheetFlushingQueue[stylesheet]); + stylesheetFlushingQueue.length = 0; + } +} +function preloadLateStyles(styleQueue) { + styleQueue.sheets.forEach(preloadLateStyle, this); + styleQueue.sheets.clear(); +} +function writeStyleResourceDependenciesInJS(destination, hoistableState) { + destination.push("["); + var nextArrayOpenBrackChunk = "["; + hoistableState.stylesheets.forEach(function (resource) { + if (2 !== resource.state) + if (3 === resource.state) + destination.push(nextArrayOpenBrackChunk), + (resource = escapeJSObjectForInstructionScripts( + "" + resource.props.href + )), + destination.push(resource), + destination.push("]"), + (nextArrayOpenBrackChunk = ",["); + else { + destination.push(nextArrayOpenBrackChunk); + var precedence = resource.props["data-precedence"], + props = resource.props, + coercedHref = sanitizeURL("" + resource.props.href); + coercedHref = escapeJSObjectForInstructionScripts(coercedHref); + destination.push(coercedHref); + precedence = "" + precedence; + destination.push(","); + precedence = escapeJSObjectForInstructionScripts(precedence); + destination.push(precedence); + for (var propKey in props) + if ( + hasOwnProperty.call(props, propKey) && + ((precedence = props[propKey]), null != precedence) + ) + switch (propKey) { + case "href": + case "rel": + case "precedence": + case "data-precedence": + break; + case "children": + case "dangerouslySetInnerHTML": + throw Error(formatProdErrorMessage(399, "link")); + default: + writeStyleResourceAttributeInJS( + destination, + propKey, + precedence + ); + } + destination.push("]"); + nextArrayOpenBrackChunk = ",["; + resource.state = 3; + } }); - return content; + destination.push("]"); } - -const selectedMarkerAttribute = stringToPrecomputedChunk(' selected=""'); - -function pushStartOption(target, props, formatContext) { - const selectedValue = formatContext.selectedValue; - target.push(startChunkForTag('option')); - let children = null; - let value = null; - let selected = null; - let innerHTML = null; - - for (const propKey in props) { - if (hasOwnProperty.call(props, propKey)) { - const propValue = props[propKey]; - - if (propValue == null) { - continue; +function writeStyleResourceAttributeInJS(destination, name, value) { + var attributeName = name.toLowerCase(); + switch (typeof value) { + case "function": + case "symbol": + return; + } + switch (name) { + case "innerHTML": + case "dangerouslySetInnerHTML": + case "suppressContentEditableWarning": + case "suppressHydrationWarning": + case "style": + case "ref": + return; + case "className": + attributeName = "class"; + name = "" + value; + break; + case "hidden": + if (!1 === value) return; + name = ""; + break; + case "src": + case "href": + value = sanitizeURL(value); + name = "" + value; + break; + default: + if ( + (2 < name.length && + ("o" === name[0] || "O" === name[0]) && + ("n" === name[1] || "N" === name[1])) || + !isAttributeNameSafe(name) + ) + return; + name = "" + value; + } + destination.push(","); + attributeName = escapeJSObjectForInstructionScripts(attributeName); + destination.push(attributeName); + destination.push(","); + attributeName = escapeJSObjectForInstructionScripts(name); + destination.push(attributeName); +} +function writeStyleResourceDependenciesInAttr(destination, hoistableState) { + destination.push("["); + var nextArrayOpenBrackChunk = "["; + hoistableState.stylesheets.forEach(function (resource) { + if (2 !== resource.state) + if (3 === resource.state) + destination.push(nextArrayOpenBrackChunk), + (resource = escapeTextForBrowser( + JSON.stringify("" + resource.props.href) + )), + destination.push(resource), + destination.push("]"), + (nextArrayOpenBrackChunk = ",["); + else { + destination.push(nextArrayOpenBrackChunk); + var precedence = resource.props["data-precedence"], + props = resource.props, + coercedHref = sanitizeURL("" + resource.props.href); + coercedHref = escapeTextForBrowser(JSON.stringify(coercedHref)); + destination.push(coercedHref); + precedence = "" + precedence; + destination.push(","); + precedence = escapeTextForBrowser(JSON.stringify(precedence)); + destination.push(precedence); + for (var propKey in props) + if ( + hasOwnProperty.call(props, propKey) && + ((precedence = props[propKey]), null != precedence) + ) + switch (propKey) { + case "href": + case "rel": + case "precedence": + case "data-precedence": + break; + case "children": + case "dangerouslySetInnerHTML": + throw Error(formatProdErrorMessage(399, "link")); + default: + writeStyleResourceAttributeInAttr( + destination, + propKey, + precedence + ); + } + destination.push("]"); + nextArrayOpenBrackChunk = ",["; + resource.state = 3; } - - switch (propKey) { - case 'children': - children = propValue; + }); + destination.push("]"); +} +function writeStyleResourceAttributeInAttr(destination, name, value) { + var attributeName = name.toLowerCase(); + switch (typeof value) { + case "function": + case "symbol": + return; + } + switch (name) { + case "innerHTML": + case "dangerouslySetInnerHTML": + case "suppressContentEditableWarning": + case "suppressHydrationWarning": + case "style": + case "ref": + return; + case "className": + attributeName = "class"; + name = "" + value; + break; + case "hidden": + if (!1 === value) return; + name = ""; + break; + case "src": + case "href": + value = sanitizeURL(value); + name = "" + value; + break; + default: + if ( + (2 < name.length && + ("o" === name[0] || "O" === name[0]) && + ("n" === name[1] || "N" === name[1])) || + !isAttributeNameSafe(name) + ) + return; + name = "" + value; + } + destination.push(","); + attributeName = escapeTextForBrowser(JSON.stringify(attributeName)); + destination.push(attributeName); + destination.push(","); + attributeName = escapeTextForBrowser(JSON.stringify(name)); + destination.push(attributeName); +} +function createHoistableState() { + return { styles: new Set(), stylesheets: new Set() }; +} +function prefetchDNS(href) { + var request = currentRequest ? currentRequest : null; + if (request) { + var resumableState = request.resumableState, + renderState = request.renderState; + if ("string" === typeof href && href) { + if (!resumableState.dnsResources.hasOwnProperty(href)) { + resumableState.dnsResources[href] = null; + resumableState = renderState.headers; + var header, JSCompiler_temp; + if ( + (JSCompiler_temp = + resumableState && 0 < resumableState.remainingCapacity) + ) + JSCompiler_temp = + ((header = + "<" + + ("" + href).replace( + regexForHrefInLinkHeaderURLContext, + escapeHrefForLinkHeaderURLContextReplacer + ) + + ">; rel=dns-prefetch"), + 2 <= (resumableState.remainingCapacity -= header.length)); + JSCompiler_temp + ? ((renderState.resets.dns[href] = null), + resumableState.preconnects && (resumableState.preconnects += ", "), + (resumableState.preconnects += header)) + : ((header = []), + pushLinkImpl(header, { href: href, rel: "dns-prefetch" }), + renderState.preconnects.add(header)); + } + enqueueFlush(request); + } + } else previousDispatcher.D(href); +} +function preconnect(href, crossOrigin) { + var request = currentRequest ? currentRequest : null; + if (request) { + var resumableState = request.resumableState, + renderState = request.renderState; + if ("string" === typeof href && href) { + var bucket = + "use-credentials" === crossOrigin + ? "credentials" + : "string" === typeof crossOrigin + ? "anonymous" + : "default"; + if (!resumableState.connectResources[bucket].hasOwnProperty(href)) { + resumableState.connectResources[bucket][href] = null; + resumableState = renderState.headers; + var header, JSCompiler_temp; + if ( + (JSCompiler_temp = + resumableState && 0 < resumableState.remainingCapacity) + ) { + JSCompiler_temp = + "<" + + ("" + href).replace( + regexForHrefInLinkHeaderURLContext, + escapeHrefForLinkHeaderURLContextReplacer + ) + + ">; rel=preconnect"; + if ("string" === typeof crossOrigin) { + var escapedCrossOrigin = ("" + crossOrigin).replace( + regexForLinkHeaderQuotedParamValueContext, + escapeStringForLinkHeaderQuotedParamValueContextReplacer + ); + JSCompiler_temp += '; crossorigin="' + escapedCrossOrigin + '"'; + } + JSCompiler_temp = + ((header = JSCompiler_temp), + 2 <= (resumableState.remainingCapacity -= header.length)); + } + JSCompiler_temp + ? ((renderState.resets.connect[bucket][href] = null), + resumableState.preconnects && (resumableState.preconnects += ", "), + (resumableState.preconnects += header)) + : ((bucket = []), + pushLinkImpl(bucket, { + rel: "preconnect", + href: href, + crossOrigin: crossOrigin + }), + renderState.preconnects.add(bucket)); + } + enqueueFlush(request); + } + } else previousDispatcher.C(href, crossOrigin); +} +function preload(href, as, options) { + var request = currentRequest ? currentRequest : null; + if (request) { + var resumableState = request.resumableState, + renderState = request.renderState; + if (as && href) { + switch (as) { + case "image": + if (options) { + var imageSrcSet = options.imageSrcSet; + var imageSizes = options.imageSizes; + var fetchPriority = options.fetchPriority; + } + var key = imageSrcSet + ? imageSrcSet + "\n" + (imageSizes || "") + : href; + if (resumableState.imageResources.hasOwnProperty(key)) return; + resumableState.imageResources[key] = PRELOAD_NO_CREDS; + resumableState = renderState.headers; + var header; + resumableState && + 0 < resumableState.remainingCapacity && + "high" === fetchPriority && + ((header = getPreloadAsHeader(href, as, options)), + 2 <= (resumableState.remainingCapacity -= header.length)) + ? ((renderState.resets.image[key] = PRELOAD_NO_CREDS), + resumableState.highImagePreloads && + (resumableState.highImagePreloads += ", "), + (resumableState.highImagePreloads += header)) + : ((resumableState = []), + pushLinkImpl( + resumableState, + assign( + { rel: "preload", href: imageSrcSet ? void 0 : href, as: as }, + options + ) + ), + "high" === fetchPriority + ? renderState.highImagePreloads.add(resumableState) + : (renderState.bulkPreloads.add(resumableState), + renderState.preloads.images.set(key, resumableState))); break; - - case 'selected': - // ignore - selected = propValue; - + case "style": + if (resumableState.styleResources.hasOwnProperty(href)) return; + imageSrcSet = []; + pushLinkImpl( + imageSrcSet, + assign({ rel: "preload", href: href, as: as }, options) + ); + resumableState.styleResources[href] = + !options || + ("string" !== typeof options.crossOrigin && + "string" !== typeof options.integrity) + ? PRELOAD_NO_CREDS + : [options.crossOrigin, options.integrity]; + renderState.preloads.stylesheets.set(href, imageSrcSet); + renderState.bulkPreloads.add(imageSrcSet); break; - - case 'dangerouslySetInnerHTML': - innerHTML = propValue; + case "script": + if (resumableState.scriptResources.hasOwnProperty(href)) return; + imageSrcSet = []; + renderState.preloads.scripts.set(href, imageSrcSet); + renderState.bulkPreloads.add(imageSrcSet); + pushLinkImpl( + imageSrcSet, + assign({ rel: "preload", href: href, as: as }, options) + ); + resumableState.scriptResources[href] = + !options || + ("string" !== typeof options.crossOrigin && + "string" !== typeof options.integrity) + ? PRELOAD_NO_CREDS + : [options.crossOrigin, options.integrity]; break; - - case 'value': - value = propValue; - // We intentionally fallthrough to also set the attribute on the node. - default: - pushAttribute(target, propKey, propValue); - break; + if (resumableState.unknownResources.hasOwnProperty(as)) { + if ( + ((imageSrcSet = resumableState.unknownResources[as]), + imageSrcSet.hasOwnProperty(href)) + ) + return; + } else + (imageSrcSet = {}), + (resumableState.unknownResources[as] = imageSrcSet); + imageSrcSet[href] = PRELOAD_NO_CREDS; + if ( + (resumableState = renderState.headers) && + 0 < resumableState.remainingCapacity && + "font" === as && + ((key = getPreloadAsHeader(href, as, options)), + 2 <= (resumableState.remainingCapacity -= key.length)) + ) + (renderState.resets.font[href] = PRELOAD_NO_CREDS), + resumableState.fontPreloads && + (resumableState.fontPreloads += ", "), + (resumableState.fontPreloads += key); + else + switch ( + ((resumableState = []), + (href = assign({ rel: "preload", href: href, as: as }, options)), + pushLinkImpl(resumableState, href), + as) + ) { + case "font": + renderState.fontPreloads.add(resumableState); + break; + default: + renderState.bulkPreloads.add(resumableState); + } } + enqueueFlush(request); } - } - - if (selectedValue != null) { - let stringValue; - - if (value !== null) { - - stringValue = '' + value; - } else { - - stringValue = flattenOptionChildren(children); + } else previousDispatcher.L(href, as, options); +} +function preloadModule(href, options) { + var request = currentRequest ? currentRequest : null; + if (request) { + var resumableState = request.resumableState, + renderState = request.renderState; + if (href) { + var as = + options && "string" === typeof options.as ? options.as : "script"; + switch (as) { + case "script": + if (resumableState.moduleScriptResources.hasOwnProperty(href)) return; + as = []; + resumableState.moduleScriptResources[href] = + !options || + ("string" !== typeof options.crossOrigin && + "string" !== typeof options.integrity) + ? PRELOAD_NO_CREDS + : [options.crossOrigin, options.integrity]; + renderState.preloads.moduleScripts.set(href, as); + break; + default: + if (resumableState.moduleUnknownResources.hasOwnProperty(as)) { + var resources = resumableState.unknownResources[as]; + if (resources.hasOwnProperty(href)) return; + } else + (resources = {}), + (resumableState.moduleUnknownResources[as] = resources); + as = []; + resources[href] = PRELOAD_NO_CREDS; + } + pushLinkImpl(as, assign({ rel: "modulepreload", href: href }, options)); + renderState.bulkPreloads.add(as); + enqueueFlush(request); } - - if (isArray(selectedValue)) { - // multiple - for (let i = 0; i < selectedValue.length; i++) { - - const v = '' + selectedValue[i]; - - if (v === stringValue) { - target.push(selectedMarkerAttribute); - break; - } - } - } else { - - if ('' + selectedValue === stringValue) { - target.push(selectedMarkerAttribute); - } - } - } else if (selected) { - target.push(selectedMarkerAttribute); + } else previousDispatcher.m(href, options); +} +function preinitStyle(href, precedence, options) { + var request = currentRequest ? currentRequest : null; + if (request) { + var resumableState = request.resumableState, + renderState = request.renderState; + if (href) { + precedence = precedence || "default"; + var styleQueue = renderState.styles.get(precedence), + resourceState = resumableState.styleResources.hasOwnProperty(href) + ? resumableState.styleResources[href] + : void 0; + null !== resourceState && + ((resumableState.styleResources[href] = null), + styleQueue || + ((styleQueue = { + precedence: escapeTextForBrowser(precedence), + rules: [], + hrefs: [], + sheets: new Map() + }), + renderState.styles.set(precedence, styleQueue)), + (precedence = { + state: 0, + props: assign( + { rel: "stylesheet", href: href, "data-precedence": precedence }, + options + ) + }), + resourceState && + (2 === resourceState.length && + adoptPreloadCredentials(precedence.props, resourceState), + (renderState = renderState.preloads.stylesheets.get(href)) && + 0 < renderState.length + ? (renderState.length = 0) + : (precedence.state = 1)), + styleQueue.sheets.set(href, precedence), + enqueueFlush(request)); + } + } else previousDispatcher.S(href, precedence, options); +} +function preinitScript(src, options) { + var request = currentRequest ? currentRequest : null; + if (request) { + var resumableState = request.resumableState, + renderState = request.renderState; + if (src) { + var resourceState = resumableState.scriptResources.hasOwnProperty(src) + ? resumableState.scriptResources[src] + : void 0; + null !== resourceState && + ((resumableState.scriptResources[src] = null), + (options = assign({ src: src, async: !0 }, options)), + resourceState && + (2 === resourceState.length && + adoptPreloadCredentials(options, resourceState), + (src = renderState.preloads.scripts.get(src))) && + (src.length = 0), + (src = []), + renderState.scripts.add(src), + pushScriptImpl(src, options), + enqueueFlush(request)); + } + } else previousDispatcher.X(src, options); +} +function preinitModuleScript(src, options) { + var request = currentRequest ? currentRequest : null; + if (request) { + var resumableState = request.resumableState, + renderState = request.renderState; + if (src) { + var resourceState = resumableState.moduleScriptResources.hasOwnProperty( + src + ) + ? resumableState.moduleScriptResources[src] + : void 0; + null !== resourceState && + ((resumableState.moduleScriptResources[src] = null), + (options = assign({ src: src, type: "module", async: !0 }, options)), + resourceState && + (2 === resourceState.length && + adoptPreloadCredentials(options, resourceState), + (src = renderState.preloads.moduleScripts.get(src))) && + (src.length = 0), + (src = []), + renderState.scripts.add(src), + pushScriptImpl(src, options), + enqueueFlush(request)); + } + } else previousDispatcher.M(src, options); +} +function adoptPreloadCredentials(target, preloadState) { + null == target.crossOrigin && (target.crossOrigin = preloadState[0]); + null == target.integrity && (target.integrity = preloadState[1]); +} +function getPreloadAsHeader(href, as, params) { + href = ("" + href).replace( + regexForHrefInLinkHeaderURLContext, + escapeHrefForLinkHeaderURLContextReplacer + ); + as = ("" + as).replace( + regexForLinkHeaderQuotedParamValueContext, + escapeStringForLinkHeaderQuotedParamValueContextReplacer + ); + as = "<" + href + '>; rel=preload; as="' + as + '"'; + for (var paramName in params) + hasOwnProperty.call(params, paramName) && + ((href = params[paramName]), + "string" === typeof href && + (as += + "; " + + paramName.toLowerCase() + + '="' + + ("" + href).replace( + regexForLinkHeaderQuotedParamValueContext, + escapeStringForLinkHeaderQuotedParamValueContextReplacer + ) + + '"')); + return as; +} +var regexForHrefInLinkHeaderURLContext = /[<>\r\n]/g; +function escapeHrefForLinkHeaderURLContextReplacer(match) { + switch (match) { + case "<": + return "%3C"; + case ">": + return "%3E"; + case "\n": + return "%0A"; + case "\r": + return "%0D"; + default: + throw Error( + "escapeLinkHrefForHeaderContextReplacer encountered a match it does not know how to replace. this means the match regex and the replacement characters are no longer in sync. This is a bug in React" + ); } - - target.push(endOfStartTag); - pushInnerHTML(target, innerHTML, children); - return children; } - -const formReplayingRuntimeScript = stringToPrecomputedChunk(formReplaying); - -function injectFormReplayingRuntime(resumableState, renderState) { - // If we haven't sent it yet, inject the runtime that tracks submitted JS actions - // for later replaying by Fiber. If we use an external runtime, we don't need - // to emit anything. It's always used. - if ((resumableState.instructions & SentFormReplayingRuntime) === NothingSent && (!renderState.externalRuntimeScript)) { - resumableState.instructions |= SentFormReplayingRuntime; - renderState.bootstrapChunks.unshift(renderState.startInlineScript, formReplayingRuntimeScript, endInlineScript); +var regexForLinkHeaderQuotedParamValueContext = /["';,\r\n]/g; +function escapeStringForLinkHeaderQuotedParamValueContextReplacer(match) { + switch (match) { + case '"': + return "%22"; + case "'": + return "%27"; + case ";": + return "%3B"; + case ",": + return "%2C"; + case "\n": + return "%0A"; + case "\r": + return "%0D"; + default: + throw Error( + "escapeStringForLinkHeaderQuotedParamValueContextReplacer encountered a match it does not know how to replace. this means the match regex and the replacement characters are no longer in sync. This is a bug in React" + ); } } - -const formStateMarkerIsMatching = stringToPrecomputedChunk(''); -const formStateMarkerIsNotMatching = stringToPrecomputedChunk(''); -function pushFormStateMarkerIsMatching(target) { - target.push(formStateMarkerIsMatching); +function hoistStyleQueueDependency(styleQueue) { + this.styles.add(styleQueue); } -function pushFormStateMarkerIsNotMatching(target) { - target.push(formStateMarkerIsNotMatching); +function hoistStylesheetDependency(stylesheet) { + this.stylesheets.add(stylesheet); } - -function pushStartForm(target, props, resumableState, renderState) { - target.push(startChunkForTag('form')); - let children = null; - let innerHTML = null; - let formAction = null; - let formEncType = null; - let formMethod = null; - let formTarget = null; - - for (const propKey in props) { - if (hasOwnProperty.call(props, propKey)) { - const propValue = props[propKey]; - - if (propValue == null) { - continue; - } - - switch (propKey) { - case 'children': - children = propValue; - break; - - case 'dangerouslySetInnerHTML': - innerHTML = propValue; - break; - - case 'action': - formAction = propValue; - break; - - case 'encType': - formEncType = propValue; - break; - - case 'method': - formMethod = propValue; - break; - - case 'target': - formTarget = propValue; - break; - - default: - pushAttribute(target, propKey, propValue); - break; - } - } +function createRenderState(resumableState, generateStaticMarkup) { + var idPrefix = resumableState.idPrefix, + bootstrapChunks = [], + bootstrapScriptContent = resumableState.bootstrapScriptContent, + bootstrapScripts = resumableState.bootstrapScripts, + bootstrapModules = resumableState.bootstrapModules; + void 0 !== bootstrapScriptContent && + bootstrapChunks.push( + "'); -const completeSegmentData1 = stringToPrecomputedChunk('')} -function Hc(a,b,c,d){switch(c.insertionMode){case 0:case 1:case 2:return a.push('}> + + + + ) +} + +export const slugs = ['a', 'b', 'c'] + +export const generateStaticParams = () => { + return slugs.map((slug) => ({ slug })) +} diff --git a/test/e2e/app-dir/ppr-incremental/next.config.js b/test/e2e/app-dir/ppr-incremental/next.config.js new file mode 100644 index 0000000000000..4120ad23231ea --- /dev/null +++ b/test/e2e/app-dir/ppr-incremental/next.config.js @@ -0,0 +1,8 @@ +/** + * @type {import('next').NextConfig} + */ +module.exports = { + experimental: { + ppr: 'incremental', + }, +} diff --git a/test/e2e/app-dir/ppr-incremental/ppr-incremental.test.ts b/test/e2e/app-dir/ppr-incremental/ppr-incremental.test.ts new file mode 100644 index 0000000000000..deb5b7e2f2315 --- /dev/null +++ b/test/e2e/app-dir/ppr-incremental/ppr-incremental.test.ts @@ -0,0 +1,177 @@ +import { nextTestSetup, isNextDev } from 'e2e-utils' + +type Route = { + route: string + enabled: boolean + pathnames: string[] +} + +const routes: ReadonlyArray = [ + { + route: '/', + pathnames: ['/'], + enabled: false, + }, + { + route: '/disabled', + pathnames: ['/disabled'], + enabled: false, + }, + { + route: '/enabled', + pathnames: ['/enabled'], + enabled: true, + }, + { + route: '/omitted/[slug]', + pathnames: ['/omitted/a', '/omitted/b', '/omitted/c'], + enabled: false, + }, + { + route: '/omitted/disabled/[slug]', + pathnames: [ + '/omitted/disabled/a', + '/omitted/disabled/b', + '/omitted/disabled/c', + ], + enabled: false, + }, + { + route: '/omitted/enabled/[slug]', + pathnames: [ + '/omitted/enabled/a', + '/omitted/enabled/b', + '/omitted/enabled/c', + ], + enabled: true, + }, + { + route: '/dynamic/[slug]', + pathnames: ['/dynamic/a', '/dynamic/b', '/dynamic/c'], + enabled: false, + }, + { + route: '/dynamic/disabled/[slug]', + pathnames: [ + '/dynamic/disabled/a', + '/dynamic/disabled/b', + '/dynamic/disabled/c', + ], + enabled: false, + }, + { + route: '/dynamic/enabled/[slug]', + pathnames: [ + '/dynamic/enabled/a', + '/dynamic/enabled/b', + '/dynamic/enabled/c', + ], + enabled: true, + }, + { + route: '/nested/enabled/[slug]', + pathnames: ['/nested/enabled/a', '/nested/enabled/b', '/nested/enabled/c'], + enabled: true, + }, + { + route: '/nested/enabled/disabled/[slug]', + pathnames: [ + '/nested/enabled/disabled/a', + '/nested/enabled/disabled/b', + '/nested/enabled/disabled/c', + ], + enabled: false, + }, + { + route: '/nested/enabled/enabled/[slug]', + pathnames: [ + '/nested/enabled/enabled/a', + '/nested/enabled/enabled/b', + '/nested/enabled/enabled/c', + ], + enabled: true, + }, + { + route: '/nested/disabled/[slug]', + pathnames: [ + '/nested/disabled/a', + '/nested/disabled/b', + '/nested/disabled/c', + ], + enabled: false, + }, + { + route: '/nested/disabled/disabled/[slug]', + pathnames: [ + '/nested/disabled/disabled/a', + '/nested/disabled/disabled/b', + '/nested/disabled/disabled/c', + ], + enabled: false, + }, + { + route: '/nested/disabled/enabled/[slug]', + pathnames: [ + '/nested/disabled/enabled/a', + '/nested/disabled/enabled/b', + '/nested/disabled/enabled/c', + ], + enabled: true, + }, +] + +describe('ppr-incremental', () => { + // We don't perform static builds and partial prerendering in development + // mode. + if (isNextDev) return it.skip('should skip next dev', () => {}) + + const { next } = nextTestSetup({ files: __dirname }) + + describe('ppr disabled', () => { + describe.each(routes.filter(({ enabled }) => !enabled))( + '$route', + ({ pathnames }) => { + // When PPR is disabled, we won't include the fallback in the initial + // load because the dynamic render will not suspend. + describe('should render without the fallback in the initial load', () => { + it.each(pathnames)('%s', async (pathname) => { + const $ = await next.render$(pathname) + expect($('#fallback')).toHaveLength(0) + }) + }) + + describe('should not have the dynamic content hidden', () => { + it.each(pathnames)('%s', async (pathname) => { + const $ = await next.render$(pathname) + expect($('#dynamic')).toHaveLength(1) + expect($('#dynamic').parent('[hidden]')).toHaveLength(0) + }) + }) + } + ) + }) + + describe('ppr enabled', () => { + describe.each(routes.filter(({ enabled }) => enabled))( + '$route', + ({ pathnames }) => { + // When PPR is enabled, we will always include the fallback in the + // initial load because the dynamic component uses `unstable_noStore()`. + describe('should render with the fallback in the initial load', () => { + it.each(pathnames)('%s', async (pathname) => { + const $ = await next.render$(pathname) + expect($('#fallback')).toHaveLength(1) + }) + }) + + describe('should have the dynamic content hidden', () => { + it.each(pathnames)('%s', async (pathname) => { + const $ = await next.render$(pathname) + expect($('#dynamic')).toHaveLength(1) + expect($('#dynamic').parent('[hidden]')).toHaveLength(1) + }) + }) + } + ) + }) +}) diff --git a/test/e2e/app-dir/rewrites-redirects/rewrites-redirects.test.ts b/test/e2e/app-dir/rewrites-redirects/rewrites-redirects.test.ts index cb4427d5e6555..c0b33a1d51f30 100644 --- a/test/e2e/app-dir/rewrites-redirects/rewrites-redirects.test.ts +++ b/test/e2e/app-dir/rewrites-redirects/rewrites-redirects.test.ts @@ -4,8 +4,8 @@ describe('redirects and rewrites', () => { const { next } = nextTestSetup({ files: __dirname, dependencies: { - react: 'latest', - 'react-dom': 'latest', + react: '19.0.0-beta-4508873393-20240430', + 'react-dom': '19.0.0-beta-4508873393-20240430', typescript: 'latest', '@types/react': 'latest', '@types/node': 'latest', diff --git a/test/e2e/app-dir/rsc-basic/next.config.js b/test/e2e/app-dir/rsc-basic/next.config.js index 9694085918594..dc925a7303fe3 100644 --- a/test/e2e/app-dir/rsc-basic/next.config.js +++ b/test/e2e/app-dir/rsc-basic/next.config.js @@ -3,9 +3,7 @@ module.exports = { onDemandEntries: { maxInactiveAge: 1000 * 60 * 60, }, - experimental: { - serverComponentsExternalPackages: ['conditional-exports-optout'], - }, + serverExternalPackages: ['conditional-exports-optout'], rewrites: async () => { return { afterFiles: [ diff --git a/test/e2e/app-dir/rsc-basic/rsc-basic.test.ts b/test/e2e/app-dir/rsc-basic/rsc-basic.test.ts index 0c9fd32989214..a188fc40ec268 100644 --- a/test/e2e/app-dir/rsc-basic/rsc-basic.test.ts +++ b/test/e2e/app-dir/rsc-basic/rsc-basic.test.ts @@ -456,11 +456,10 @@ describe('app dir - rsc basics', () => { // TODO: (PPR) remove once PPR is stable const bundledReactVersionPattern = - process.env.__NEXT_EXPERIMENTAL_PPR === 'true' - ? '-experimental-' - : '-canary-' + process.env.__NEXT_EXPERIMENTAL_PPR === 'true' ? '-experimental-' : '-beta-' - it('should not use bundled react for pages with app', async () => { + // TODO: (React 19) During Beta, bundled and installed version match. + it.skip('should not use bundled react for pages with app', async () => { const ssrPaths = ['/pages-react', '/edge-pages-react'] const promises = ssrPaths.map(async (pathname) => { const resPages$ = await next.render$(pathname) diff --git a/test/e2e/app-dir/server-components-externals/index.test.ts b/test/e2e/app-dir/server-components-externals/index.test.ts index 99845d6cb2def..cad7e4c60e6bc 100644 --- a/test/e2e/app-dir/server-components-externals/index.test.ts +++ b/test/e2e/app-dir/server-components-externals/index.test.ts @@ -6,7 +6,7 @@ describe('app-dir - server components externals', () => { files: __dirname, }) - it('should have externals for those in config.experimental.serverComponentsExternalPackages', async () => { + it('should have externals for those in config.serverExternalPackages', async () => { const $ = await next.render$('/') const text = $('#directory').text() @@ -28,7 +28,7 @@ describe('app-dir - server components externals', () => { // Inspect webpack server bundles if (!isTurbopack) { - it('should externalize serverComponentsExternalPackages for server rendering layer', async () => { + it('should externalize serversExternalPackages for server rendering layer', async () => { await next.fetch('/client') const ssrBundle = await next.readFile('.next/server/app/client/page.js') expect(ssrBundle).not.toContain('external-package-mark:index') diff --git a/test/e2e/app-dir/server-components-externals/next.config.js b/test/e2e/app-dir/server-components-externals/next.config.js index 3abed8085c5e4..f567efc88411a 100644 --- a/test/e2e/app-dir/server-components-externals/next.config.js +++ b/test/e2e/app-dir/server-components-externals/next.config.js @@ -2,9 +2,7 @@ * @type {import('next').NextConfig} */ const nextConfig = { - experimental: { - serverComponentsExternalPackages: ['external-package'], - }, + serverExternalPackages: ['external-package'], } module.exports = nextConfig diff --git a/test/e2e/dynamic-route-interpolation/index.test.ts b/test/e2e/dynamic-route-interpolation/index.test.ts index a7c296d422bc9..9c10505c67bdc 100644 --- a/test/e2e/dynamic-route-interpolation/index.test.ts +++ b/test/e2e/dynamic-route-interpolation/index.test.ts @@ -61,9 +61,8 @@ describe('Dynamic Route Interpolation', () => { } // e.g. /_next/static/chunks/pages/blog/%5Bslug%5D-3d2fedc300f04305.js - const { status: encodedPathReqStatus } = await next.fetch( - pagePathScriptSrc - ) + const { status: encodedPathReqStatus } = + await next.fetch(pagePathScriptSrc) // e.g. /_next/static/chunks/pages/blog/[slug]-3d2fedc300f04305.js const { status: decodedPathReqStatus } = await next.fetch( decodeURI(pagePathScriptSrc) diff --git a/test/e2e/esm-externals/esm-externals.test.ts b/test/e2e/esm-externals/esm-externals.test.ts index 4832bb6b58819..be5b8340b137b 100644 --- a/test/e2e/esm-externals/esm-externals.test.ts +++ b/test/e2e/esm-externals/esm-externals.test.ts @@ -13,13 +13,15 @@ describe('esm-externals', () => { const urls = ['/static', '/ssr', '/ssg'] for (const url of urls) { - // TODO fix webpack behavior + // For invalid esm packages that have "import" pointing to a non-esm-flagged module + // webpack is using the CJS version instead but Turbopack is opting out of + // externalizing and bundling the non-esm-flagged module. const expectedHtml = isTurbopack ? /Hello World\+World\+World\+World\+World\+World/ : url === '/static' - ? /Hello World\+World\+Alternative\+World\+World\+World/ - : /Hello World\+World\+Alternative\+World\+World\+Alternative/ - // TODO fix webpack behavior + ? /Hello World\+World\+Alternative\+World\+World\+World/ + : /Hello World\+World\+Alternative\+World\+World\+Alternative/ + // On client side, webpack always bundlings so it uses the non-esm-flagged module too. const expectedText = isTurbopack || url === '/static' ? /Hello World\+World\+World\+World\+World\+World/ @@ -40,18 +42,21 @@ describe('esm-externals', () => { // App dir { - // TODO App Dir doesn't use esmExternals: true correctly for webpack and Turbopack + // TODO App Dir doesn't use esmExternals: true correctly for Turbopack // so we only verify that the page doesn't crash, but ignore the actual content - // const expectedHtml = /Hello World\+World\+World/ - const expectedHtml = /Hello Wrong\+Wrong\+Alternative/ - // const expectedText = /Hello World\+World\+World/ + // const expectedHtml = isTurbopack ? /Hello World\+World\+World/ : /Hello World\+World\+Alternative/ + const expectedHtml = isTurbopack + ? /Hello Wrong\+Wrong\+Alternative/ + : /Hello World\+World\+Alternative/ const urls = ['/server', '/client'] for (const url of urls) { const expectedText = - url === '/server' - ? /Hello Wrong\+Wrong\+Alternative/ - : /Hello World\+World\+World/ + url !== '/server' + ? /Hello World\+World\+World/ + : isTurbopack + ? /Hello Wrong\+Wrong\+Alternative/ + : /Hello World\+World\+Alternative/ it(`should return the correct SSR HTML for ${url}`, async () => { const res = await next.fetch(url) const html = await res.text() diff --git a/test/e2e/esm-externals/next.config.js b/test/e2e/esm-externals/next.config.js index bb3b101d0210e..4e8f830721386 100644 --- a/test/e2e/esm-externals/next.config.js +++ b/test/e2e/esm-externals/next.config.js @@ -5,12 +5,12 @@ module.exports = { 'preact/compat': 'react', }, }, - serverComponentsExternalPackages: [ - 'app-esm-package1', - 'app-esm-package2', - 'app-cjs-esm-package', - ], }, + serverExternalPackages: [ + 'app-esm-package1', + 'app-esm-package2', + 'app-cjs-esm-package', + ], webpack(config, { isServer }) { config.resolve.alias = { ...config.resolve.alias, diff --git a/test/e2e/middleware-general/test/index.test.ts b/test/e2e/middleware-general/test/index.test.ts index e5c23b4fe51ca..c8100fc95952b 100644 --- a/test/e2e/middleware-general/test/index.test.ts +++ b/test/e2e/middleware-general/test/index.test.ts @@ -170,9 +170,9 @@ describe('Middleware Runtime', () => { ...manifest.middleware['/'], } const envs = { - ...middlewareWithoutEnvs.environments, + ...middlewareWithoutEnvs.env, } - delete middlewareWithoutEnvs.environments + delete middlewareWithoutEnvs.env expect(middlewareWithoutEnvs).toEqual({ files: expect.arrayContaining([ 'server/edge-runtime-webpack.js', @@ -186,9 +186,11 @@ describe('Middleware Runtime', () => { regions: 'auto', }) expect(envs).toContainAllKeys([ - 'previewModeEncryptionKey', - 'previewModeId', - 'previewModeSigningKey', + 'NEXT_SERVER_ACTIONS_ENCRYPTION_KEY', + '__NEXT_BUILD_ID', + '__NEXT_PREVIEW_MODE_ENCRYPTION_KEY', + '__NEXT_PREVIEW_MODE_ID', + '__NEXT_PREVIEW_MODE_SIGNING_KEY', ]) }) diff --git a/test/e2e/middleware-trailing-slash/test/index.test.ts b/test/e2e/middleware-trailing-slash/test/index.test.ts index e6f04754930f3..1ee913f5a5578 100644 --- a/test/e2e/middleware-trailing-slash/test/index.test.ts +++ b/test/e2e/middleware-trailing-slash/test/index.test.ts @@ -112,7 +112,7 @@ describe('Middleware Runtime trailing slash', () => { const middlewareWithoutEnvs = { ...manifest.middleware['/'], } - delete middlewareWithoutEnvs.environments + delete middlewareWithoutEnvs.env expect(middlewareWithoutEnvs).toEqual({ files: expect.arrayContaining([ 'prerender-manifest.js', diff --git a/test/e2e/multi-zone/app/package.json b/test/e2e/multi-zone/app/package.json index 1ce876917a660..63102dc43820b 100644 --- a/test/e2e/multi-zone/app/package.json +++ b/test/e2e/multi-zone/app/package.json @@ -1,12 +1,5 @@ { "name": "with-zones", "version": "1.0.0", - "private": true, - "dependencies": { - "@types/react": "18.0.28", - "next": "canary", - "react": "^18.2.0", - "react-dom": "^18.2.0", - "typescript": "^4.9.3" - } + "private": true } diff --git a/test/e2e/new-link-behavior/child-a-tag-error.test.ts b/test/e2e/new-link-behavior/child-a-tag-error.test.ts index efd13c1a92d39..b0dc84c7a3b41 100644 --- a/test/e2e/new-link-behavior/child-a-tag-error.test.ts +++ b/test/e2e/new-link-behavior/child-a-tag-error.test.ts @@ -17,8 +17,8 @@ describe('New Link Behavior with child', () => { }, dependencies: { next: 'latest', - react: 'latest', - 'react-dom': 'latest', + react: '19.0.0-beta-4508873393-20240430', + 'react-dom': '19.0.0-beta-4508873393-20240430', }, }) }) diff --git a/test/e2e/new-link-behavior/material-ui.test.ts b/test/e2e/new-link-behavior/material-ui.test.ts index d3d6b9d328f27..3ee8b2e1eeb7d 100644 --- a/test/e2e/new-link-behavior/material-ui.test.ts +++ b/test/e2e/new-link-behavior/material-ui.test.ts @@ -24,8 +24,8 @@ describe('New Link Behavior with material-ui', () => { '@mui/material': 'latest', next: 'latest', 'prop-types': 'latest', - react: 'latest', - 'react-dom': 'latest', + react: '19.0.0-beta-4508873393-20240430', + 'react-dom': '19.0.0-beta-4508873393-20240430', // Use minimum peer dep version instead of v9 of eslint to avoid breaking changes eslint: '8.56.0', 'eslint-config-next': 'latest', diff --git a/test/e2e/new-link-behavior/material-ui/src/Link.js b/test/e2e/new-link-behavior/material-ui/src/Link.js index 41ea0f99ec459..fc268673f0bb9 100644 --- a/test/e2e/new-link-behavior/material-ui/src/Link.js +++ b/test/e2e/new-link-behavior/material-ui/src/Link.js @@ -6,17 +6,16 @@ import { styled } from '@mui/material/styles' // Add support for the sx prop for consistency with the other branches. const Anchor = styled(NextLink)({}) -export const NextLinkComposed = React.forwardRef(function NextLinkComposed( - props, - ref -) { - const { children, ...rest } = props - return ( - - {children} - - ) -}) +export const NextLinkComposed = React.forwardRef( + function NextLinkComposed(props, ref) { + const { children, ...rest } = props + return ( + + {children} + + ) + } +) // A styled version of the Next.js Link component: // https://nextjs.org/docs/api-reference/next/link diff --git a/test/e2e/new-link-behavior/stitches.test.ts b/test/e2e/new-link-behavior/stitches.test.ts index 063a9dde3bb1f..aa477c191e251 100644 --- a/test/e2e/new-link-behavior/stitches.test.ts +++ b/test/e2e/new-link-behavior/stitches.test.ts @@ -21,8 +21,8 @@ describe('New Link Behavior with stitches', () => { dependencies: { '@stitches/react': '^1.2.6', next: 'latest', - react: 'latest', - 'react-dom': 'latest', + react: '19.0.0-beta-4508873393-20240430', + 'react-dom': '19.0.0-beta-4508873393-20240430', }, }) }) diff --git a/test/e2e/next-font/app-old/components/CompWithFonts.js b/test/e2e/next-font/app-old/components/CompWithFonts.js deleted file mode 100644 index 69f77d15c00d1..0000000000000 --- a/test/e2e/next-font/app-old/components/CompWithFonts.js +++ /dev/null @@ -1,27 +0,0 @@ -import { Inter, Roboto } from '@next/font/google' -const inter = Inter({ - weight: '900', - display: 'swap', - preload: false, - subsets: ['latin'], -}) -const roboto = Roboto({ - weight: '100', - style: 'italic', - display: 'swap', - preload: true, - subsets: ['vietnamese'], -}) - -export default function Component() { - return ( - <> -
- {JSON.stringify(inter)} -
-
- {JSON.stringify(roboto)} -
- - ) -} diff --git a/test/e2e/next-font/app-old/fonts/my-font.woff2 b/test/e2e/next-font/app-old/fonts/my-font.woff2 deleted file mode 100644 index a6b3c3a9d69fa..0000000000000 Binary files a/test/e2e/next-font/app-old/fonts/my-font.woff2 and /dev/null differ diff --git a/test/e2e/next-font/app-old/fonts/my-other-font.woff2 b/test/e2e/next-font/app-old/fonts/my-other-font.woff2 deleted file mode 100644 index ac8adf10ed942..0000000000000 Binary files a/test/e2e/next-font/app-old/fonts/my-other-font.woff2 and /dev/null differ diff --git a/test/e2e/next-font/app-old/fonts/roboto/roboto-100-italic.woff2 b/test/e2e/next-font/app-old/fonts/roboto/roboto-100-italic.woff2 deleted file mode 100644 index 1f22fa96cdfe5..0000000000000 Binary files a/test/e2e/next-font/app-old/fonts/roboto/roboto-100-italic.woff2 and /dev/null differ diff --git a/test/e2e/next-font/app-old/fonts/roboto/roboto-100.woff2 b/test/e2e/next-font/app-old/fonts/roboto/roboto-100.woff2 deleted file mode 100644 index 921b2bb6a9de1..0000000000000 Binary files a/test/e2e/next-font/app-old/fonts/roboto/roboto-100.woff2 and /dev/null differ diff --git a/test/e2e/next-font/app-old/fonts/roboto/roboto-400-italic.woff2 b/test/e2e/next-font/app-old/fonts/roboto/roboto-400-italic.woff2 deleted file mode 100644 index fbe1a26c9c4c2..0000000000000 Binary files a/test/e2e/next-font/app-old/fonts/roboto/roboto-400-italic.woff2 and /dev/null differ diff --git a/test/e2e/next-font/app-old/fonts/roboto/roboto-400.woff2 b/test/e2e/next-font/app-old/fonts/roboto/roboto-400.woff2 deleted file mode 100644 index b65a361a2e44d..0000000000000 Binary files a/test/e2e/next-font/app-old/fonts/roboto/roboto-400.woff2 and /dev/null differ diff --git a/test/e2e/next-font/app-old/fonts/roboto/roboto-900-italic.woff2 b/test/e2e/next-font/app-old/fonts/roboto/roboto-900-italic.woff2 deleted file mode 100644 index 741d0638b1db4..0000000000000 Binary files a/test/e2e/next-font/app-old/fonts/roboto/roboto-900-italic.woff2 and /dev/null differ diff --git a/test/e2e/next-font/app-old/fonts/roboto/roboto-900.woff2 b/test/e2e/next-font/app-old/fonts/roboto/roboto-900.woff2 deleted file mode 100644 index 4b7cb645bb87f..0000000000000 Binary files a/test/e2e/next-font/app-old/fonts/roboto/roboto-900.woff2 and /dev/null differ diff --git a/test/e2e/next-font/app-old/pages/_app.js b/test/e2e/next-font/app-old/pages/_app.js deleted file mode 100644 index 00e03ccbb5314..0000000000000 --- a/test/e2e/next-font/app-old/pages/_app.js +++ /dev/null @@ -1,16 +0,0 @@ -import { Open_Sans } from '@next/font/google' -const openSans = Open_Sans({ variable: '--open-sans', subsets: ['latin'] }) - -function MyApp({ Component, pageProps }) { - return ( - <> -
- {JSON.stringify(openSans)} -
- - - ) -} - -export { openSans } -export default MyApp diff --git a/test/e2e/next-font/app-old/pages/font-without-preloadable-subsets.js b/test/e2e/next-font/app-old/pages/font-without-preloadable-subsets.js deleted file mode 100644 index 62ac7af99f5c1..0000000000000 --- a/test/e2e/next-font/app-old/pages/font-without-preloadable-subsets.js +++ /dev/null @@ -1,7 +0,0 @@ -import { Single_Day } from '@next/font/google' - -const singleDay = Single_Day({ weight: '400' }) - -export default function FontWithoutPreloadableSubsets() { - return

{JSON.stringify(singleDay)}

-} diff --git a/test/e2e/next-font/app-old/pages/variable-font-without-weight-range.js b/test/e2e/next-font/app-old/pages/variable-font-without-weight-range.js deleted file mode 100644 index 03c192d1d85cf..0000000000000 --- a/test/e2e/next-font/app-old/pages/variable-font-without-weight-range.js +++ /dev/null @@ -1,11 +0,0 @@ -import { Nabla } from '@next/font/google' - -const nabla = Nabla({ subsets: ['latin'] }) - -export default function VariableFontWithoutWeightRange() { - return ( -

- {JSON.stringify(nabla)} -

- ) -} diff --git a/test/e2e/next-font/app-old/pages/variables.js b/test/e2e/next-font/app-old/pages/variables.js deleted file mode 100644 index 6af422a3c510c..0000000000000 --- a/test/e2e/next-font/app-old/pages/variables.js +++ /dev/null @@ -1,69 +0,0 @@ -import { Fira_Code, Roboto } from '@next/font/google' -import localFont from '@next/font/local' - -const firaCode = Fira_Code({ variable: '--fira-code', subsets: ['latin'] }) -const roboto = Roboto({ - weight: '100', - style: 'italic', - display: 'swap', - preload: true, - variable: '--roboto-100-italic', - subsets: ['latin'], -}) -const myFont = localFont({ - src: '../fonts/my-font.woff2', - preload: false, - variable: '--my-font', - subsets: ['latin'], -}) - -export default function WithFonts() { - return ( - <> - {/* Fira Code Variable */} -
- With variables -
-
- Without variables -
- - {/* Roboto 100 Italic */} -
- With variables -
-
- Without variables -
- - {/* Local font */} -
- With variables -
-
- Without variables -
- - ) -} diff --git a/test/e2e/next-font/app-old/pages/with-fallback.js b/test/e2e/next-font/app-old/pages/with-fallback.js deleted file mode 100644 index 091f8d955d6a5..0000000000000 --- a/test/e2e/next-font/app-old/pages/with-fallback.js +++ /dev/null @@ -1,37 +0,0 @@ -import localFont from '@next/font/local' -import { Open_Sans } from '@next/font/google' -const openSans = Open_Sans({ - fallback: ['system-ui', 'Arial'], - variable: '--open-sans', - adjustFontFallback: false, - subsets: ['latin'], -}) - -const myFont = localFont({ - fallback: ['system-ui', 'Arial'], - src: '../fonts/my-font.woff2', - adjustFontFallback: false, -}) - -export default function WithFonts() { - return ( - <> -
- {JSON.stringify(openSans)} -
-
- {JSON.stringify(openSans)} -
-
- {JSON.stringify(openSans)} -
-
- {JSON.stringify(myFont)} -
- - ) -} diff --git a/test/e2e/next-font/app-old/pages/with-fonts.js b/test/e2e/next-font/app-old/pages/with-fonts.js deleted file mode 100644 index 13dbe3e46bf9f..0000000000000 --- a/test/e2e/next-font/app-old/pages/with-fonts.js +++ /dev/null @@ -1,14 +0,0 @@ -import CompWithFonts from '../components/CompWithFonts' -import { openSans } from './_app' - -export default function WithFonts() { - return ( - <> - -
- {JSON.stringify(openSans)} -
-
- - ) -} diff --git a/test/e2e/next-font/app-old/pages/with-google-fonts.js b/test/e2e/next-font/app-old/pages/with-google-fonts.js deleted file mode 100644 index 836e0b5422da4..0000000000000 --- a/test/e2e/next-font/app-old/pages/with-google-fonts.js +++ /dev/null @@ -1,49 +0,0 @@ -import { Fraunces, Indie_Flower, Roboto } from '@next/font/google' - -const indieFlower = Indie_Flower({ - weight: '400', - preload: false, - subsets: ['latin'], -}) -const fraunces = Fraunces({ weight: '400', preload: false, subsets: ['latin'] }) - -const robotoMultiple = Roboto({ - weight: ['900', '100'], - style: ['normal', 'italic'], - subsets: ['latin'], -}) -const frauncesMultiple = Fraunces({ - style: ['italic', 'normal'], - axes: ['SOFT', 'WONK', 'opsz'], - subsets: ['latin'], -}) - -const frauncesMultipleWeights = Fraunces({ - weight: ['100', '400', '900'], - subsets: ['latin'], -}) - -export default function WithFonts() { - return ( - <> -
- {JSON.stringify(indieFlower)} -
-
- {JSON.stringify(fraunces)} -
-
- {JSON.stringify(robotoMultiple)} -
-
- {JSON.stringify(frauncesMultiple)} -
-
- {JSON.stringify(frauncesMultipleWeights)} -
- - ) -} diff --git a/test/e2e/next-font/app-old/pages/with-local-fonts.js b/test/e2e/next-font/app-old/pages/with-local-fonts.js deleted file mode 100644 index 37f218859d243..0000000000000 --- a/test/e2e/next-font/app-old/pages/with-local-fonts.js +++ /dev/null @@ -1,153 +0,0 @@ -import localFont from '@next/font/local' - -const myFont1 = localFont({ - src: '../fonts/my-font.woff2', - style: 'italic', - weight: '100', - fallback: ['system-ui'], - adjustFontFallback: 'Times New Roman', -}) -const myFont2 = localFont({ - src: '../fonts/my-other-font.woff2', - preload: false, - variable: '--my-font', -}) - -const roboto = localFont({ - preload: false, - src: [ - { - path: '../fonts/roboto/roboto-100-italic.woff2', - weight: '100', - style: 'italic', - }, - { - path: '../fonts/my-font.woff2', - weight: '100', - style: 'normal', - }, - { - path: '../fonts/my-font.woff2', - weight: '400', - style: 'italic', - }, - { - path: '../fonts/roboto/roboto-400.woff2', - weight: '400', - }, - { - path: '../fonts/my-font.woff2', - style: 'italic', - }, - { - path: '../fonts/my-font.woff2', - weight: '900', - style: 'normal', - }, - ], -}) - -const robotoVar1 = localFont({ - preload: false, - src: [ - { - path: '../fonts/roboto/roboto-400.woff2', - weight: '100 300', - style: 'normal', - }, - { - path: '../fonts/my-font.woff2', - weight: '100 300', - style: 'italic', - }, - { - path: '../fonts/my-font.woff2', - weight: '500 900', - style: 'italic', - }, - { - path: '../fonts/my-font.woff2', - weight: '500 900', - style: 'normal', - }, - ], -}) - -const robotoVar2 = localFont({ - preload: false, - src: [ - { - path: '../fonts/roboto/roboto-900.woff2', - weight: '100 900', - style: 'italic', - }, - { - path: '../fonts/roboto/roboto-400.woff2', - weight: '100 900', - style: 'normal', - }, - { - path: '../fonts/my-font.woff2', - weight: '300 399', - style: 'italic', - }, - { - path: '../fonts/my-font.woff2', - weight: '401 500', - style: 'normal', - }, - ], -}) - -const robotoWithPreload = localFont({ - src: [ - { - path: '../fonts/roboto/roboto-100.woff2', - weight: '100', - style: 'normal', - }, - { - path: '../fonts/roboto/roboto-900-italic.woff2', - weight: '900', - style: 'italic', - }, - { - path: '../fonts/roboto/roboto-100.woff2', - weight: '100', - style: 'normal', - }, - { - path: '../fonts/roboto/roboto-100-italic.woff2', - weight: '900', - style: 'italic', - }, - ], -}) - -export default function WithFonts() { - return ( - <> -
- {JSON.stringify(myFont1)} -
-
- {JSON.stringify(myFont2)} -
-
- {JSON.stringify(roboto)} -
-
- {JSON.stringify(robotoVar1)} -
-
- {JSON.stringify(robotoVar2)} -
-
- {JSON.stringify(robotoWithPreload)} -
- - ) -} diff --git a/test/e2e/next-font/app-old/pages/without-fonts.js b/test/e2e/next-font/app-old/pages/without-fonts.js deleted file mode 100644 index 0f649722e671d..0000000000000 --- a/test/e2e/next-font/app-old/pages/without-fonts.js +++ /dev/null @@ -1,3 +0,0 @@ -export default function WithoutFonts() { - return

Hello world

-} diff --git a/test/e2e/next-font/index.test.ts b/test/e2e/next-font/index.test.ts index bd113b94a7b1a..d45cbfa92e4fd 100644 --- a/test/e2e/next-font/index.test.ts +++ b/test/e2e/next-font/index.test.ts @@ -39,618 +39,610 @@ function hrefMatchesFontWithoutSizeAdjust(href: string) { } describe('next/font', () => { - for (const fixture of ['app', 'app-old']) { - describe(fixture, () => { - // Turbopack only support `next/font` as `@next/font` is going to be removed in the next major version. - if (process.env.TURBOPACK && fixture === 'app-old') { - return - } - let next: NextInstance + let next: NextInstance - if ((global as any).isNextDeploy) { - it('should skip next deploy for now', () => {}) - return - } + if ((global as any).isNextDeploy) { + it('should skip next deploy for now', () => {}) + return + } - beforeAll(async () => { - next = await createNext({ - files: { - pages: new FileRef(join(__dirname, `${fixture}/pages`)), - components: new FileRef(join(__dirname, `${fixture}/components`)), - fonts: new FileRef(join(__dirname, `${fixture}/fonts`)), - }, - dependencies: { - '@next/font': 'canary', - }, - env: { - NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, - }, - }) + beforeAll(async () => { + next = await createNext({ + files: { + pages: new FileRef(join(__dirname, `app/pages`)), + components: new FileRef(join(__dirname, `app/components`)), + fonts: new FileRef(join(__dirname, `app/fonts`)), + }, + dependencies: { + '@next/font': 'canary', + }, + env: { + NEXT_FONT_GOOGLE_MOCKED_RESPONSES: mockedGoogleFontResponses, + }, + }) + }) + afterAll(() => next.destroy()) + + if ((global as any).isNextDev) { + it('should use production cache control for fonts', async () => { + const $ = await next.render$('/') + const link = $('[rel="preload"][as="font"]').attr('href') + expect(link).toBeDefined() + const res = await next.fetch(link) + expect(res.headers.get('cache-control')).toBe( + 'public, max-age=31536000, immutable' + ) + }) + } + + describe('import values', () => { + test('page with font', async () => { + const html = await renderViaHTTP(next.url, '/with-fonts') + const $ = cheerio.load(html) + + // _app.js + expect(JSON.parse($('#app-open-sans').text())).toEqual({ + className: expect.stringMatching(getClassNameRegex('className')), + variable: expect.stringMatching(getClassNameRegex('variable')), + style: { + fontFamily: expect.stringMatching( + /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ + ), + fontStyle: 'normal', + }, }) - afterAll(() => next.destroy()) - - if ((global as any).isNextDev) { - it('should use production cache control for fonts', async () => { - const $ = await next.render$('/') - const link = $('[rel="preload"][as="font"]').attr('href') - expect(link).toBeDefined() - const res = await next.fetch(link) - expect(res.headers.get('cache-control')).toBe( - 'public, max-age=31536000, immutable' - ) - }) + + // with-fonts.js + expect(JSON.parse($('#with-fonts-open-sans').text())).toEqual({ + className: expect.stringMatching(getClassNameRegex('className')), + variable: expect.stringMatching(getClassNameRegex('variable')), + style: { + fontFamily: expect.stringMatching( + /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ + ), + fontStyle: 'normal', + }, + }) + + // CompWithFonts.js + expect(JSON.parse($('#comp-with-fonts-inter').text())).toEqual({ + className: expect.stringMatching(getClassNameRegex('className')), + style: { + fontFamily: expect.stringMatching( + /^'__Inter_.{6}', '__Inter_Fallback_.{6}'$/ + ), + fontWeight: 900, + fontStyle: 'normal', + }, + }) + expect(JSON.parse($('#comp-with-fonts-roboto').text())).toEqual({ + className: expect.stringMatching(getClassNameRegex('className')), + style: { + fontFamily: expect.stringMatching( + /^'__Roboto_.{6}', '__Roboto_Fallback_.{6}'$/ + ), + fontStyle: 'italic', + fontWeight: 100, + }, + }) + }) + + test('page with local fonts', async () => { + const html = await renderViaHTTP(next.url, '/with-local-fonts') + const $ = cheerio.load(html) + + // _app.js + expect(JSON.parse($('#app-open-sans').text())).toEqual({ + className: expect.stringMatching(getClassNameRegex('className')), + variable: expect.stringMatching(getClassNameRegex('variable')), + style: { + fontFamily: expect.stringMatching( + /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ + ), + fontStyle: 'normal', + }, + }) + + // with-local-fonts.js + expect(JSON.parse($('#first-local-font').text())).toEqual({ + className: expect.stringMatching(getClassNameRegex('className')), + style: { + fontFamily: expect.stringMatching( + /^'__myFont1_.{6}', '__myFont1_Fallback_.{6}', system-ui$/ + ), + fontStyle: 'italic', + fontWeight: 100, + }, + }) + expect(JSON.parse($('#second-local-font').text())).toEqual({ + className: expect.stringMatching(getClassNameRegex('className')), + variable: expect.stringMatching(getClassNameRegex('variable')), + style: { + fontFamily: expect.stringMatching( + /^'__myFont2_.{6}', '__myFont2_Fallback_.{6}'$/ + ), + }, + }) + }) + + test('Variable font without weight range', async () => { + const html = await renderViaHTTP( + next.url, + '/variable-font-without-weight-range' + ) + const $ = cheerio.load(html) + + expect(JSON.parse($('#nabla').text())).toEqual({ + className: expect.stringMatching(getClassNameRegex('className')), + style: { + fontFamily: expect.stringMatching( + /^'__Nabla_.{6}', '__Nabla_Fallback_.{6}'$/ + ), + fontStyle: 'normal', + }, + }) + }) + }) + + describe('computed styles', () => { + test('page with fonts', async () => { + const browser = await webdriver(next.url, '/with-fonts') + + // _app.js + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#app-open-sans")).fontFamily' + ) + ).toMatch(/^__Open_Sans_.{6}, __Open_Sans_Fallback_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#app-open-sans")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#app-open-sans")).fontStyle' + ) + ).toBe('normal') + + // with-fonts.js + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontFamily' + ) + ).toMatch(/^__Open_Sans_.{6}, __Open_Sans_Fallback_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontStyle' + ) + ).toBe('normal') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fonts-open-sans-style")).fontWeight' + ) + ).toBe('400') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fonts-open-sans-style")).fontStyle' + ) + ).toBe('normal') + + // CompWithFonts.js + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontFamily' + ) + ).toMatch(/^__Inter_.{6}, __Inter_Fallback_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontWeight' + ) + ).toBe('900') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontStyle' + ) + ).toBe('normal') + + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontFamily' + ) + ).toMatch(/^__Roboto_.{6}, __Roboto_Fallback_.{6}$/) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontWeight' + ) + ).toBe('100') + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontStyle' + ) + ).toBe('italic') + }) + + test('page using variables', async () => { + const browser = await webdriver(next.url, '/variables') + + // Fira Code Variable + const firaCodeRegex = /^__Fira_Code_.{6}, __Fira_Code_Fallback_.{6}$/ + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#variables-fira-code")).fontFamily' + ) + ).toMatch(firaCodeRegex) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#without-variables-fira-code")).fontFamily' + ) + ).not.toMatch(firaCodeRegex) + + // Roboto 100 Italic + const roboto100ItalicRegex = /^__Roboto_.{6}, __Roboto_Fallback_.{6}$/ + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#variables-roboto-100-italic")).fontFamily' + ) + ).toMatch(roboto100ItalicRegex) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#without-variables-roboto-100-italic")).fontFamily' + ) + ).not.toMatch(roboto100ItalicRegex) + + // Local font + const localFontRegex = /^__myFont_.{6}, __myFont_Fallback_.{6}$/ + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#variables-local-font")).fontFamily' + ) + ).toMatch(localFontRegex) + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#without-variables-local-font")).fontFamily' + ) + ).not.toMatch(localFontRegex) + }) + + test('page using fallback fonts', async () => { + const browser = await webdriver(next.url, '/with-fallback') + + // .className + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fallback-fonts-classname")).fontFamily' + ) + ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) + + // .style + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fallback-fonts-style")).fontFamily' + ) + ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) + + // .variable + expect( + await browser.eval( + 'getComputedStyle(document.querySelector("#with-fallback-fonts-variable")).fontFamily' + ) + ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) + }) + }) + + describe('preload', () => { + test('page with fonts', async () => { + const html = await renderViaHTTP(next.url, '/with-fonts') + const $ = cheerio.load(html) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + expect($('link[as="font"]').length).toBe(2) + const links = Array.from($('link[as="font"]')).sort((a, b) => { + return a.attribs.href.localeCompare(b.attribs.href) + }) + // From /_app + const attributes = links[0].attribs + expect(attributes.as).toBe('font') + expect(attributes.crossorigin).toBe('anonymous') + hrefMatchesFontWithSizeAdjust(attributes.href) + expect(attributes.rel).toBe('preload') + expect(attributes.type).toBe('font/woff2') + expect(attributes['data-next-font']).toBe('size-adjust') + + const attributes2 = links[1].attribs + expect(attributes2.as).toBe('font') + expect(attributes2.crossorigin).toBe('anonymous') + hrefMatchesFontWithSizeAdjust(attributes2.href) + expect(attributes2.rel).toBe('preload') + expect(attributes2.type).toBe('font/woff2') + expect(attributes2['data-next-font']).toBe('size-adjust') + }) + + test('page without fonts', async () => { + const html = await renderViaHTTP(next.url, '/without-fonts') + const $ = cheerio.load(html) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // From _app + expect($('link[as="font"]').length).toBe(1) + + const attributes = $('link[as="font"]').get(0).attribs + expect(attributes.as).toBe('font') + expect(attributes.crossorigin).toBe('anonymous') + hrefMatchesFontWithSizeAdjust(attributes.href) + expect(attributes.rel).toBe('preload') + expect(attributes.type).toBe('font/woff2') + expect(attributes['data-next-font']).toBe('size-adjust') + }) + + test('page with local fonts', async () => { + const html = await renderViaHTTP(next.url, '/with-local-fonts') + const $ = cheerio.load(html) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // Preload + expect($('link[as="font"]').length).toBe(5) + const hrefs = Array.from($('link[as="font"]')) + .map((el) => el.attribs.href) + .sort() + for (const href of hrefs) { + hrefMatchesFontWithSizeAdjust(href) } + expect(hrefs.length).toBe(5) + }) - describe('import values', () => { - test('page with font', async () => { - const html = await renderViaHTTP(next.url, '/with-fonts') - const $ = cheerio.load(html) - - // _app.js - expect(JSON.parse($('#app-open-sans').text())).toEqual({ - className: expect.stringMatching(getClassNameRegex('className')), - variable: expect.stringMatching(getClassNameRegex('variable')), - style: { - fontFamily: expect.stringMatching( - /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ - ), - fontStyle: 'normal', - }, - }) - - // with-fonts.js - expect(JSON.parse($('#with-fonts-open-sans').text())).toEqual({ - className: expect.stringMatching(getClassNameRegex('className')), - variable: expect.stringMatching(getClassNameRegex('variable')), - style: { - fontFamily: expect.stringMatching( - /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ - ), - fontStyle: 'normal', - }, - }) - - // CompWithFonts.js - expect(JSON.parse($('#comp-with-fonts-inter').text())).toEqual({ - className: expect.stringMatching(getClassNameRegex('className')), - style: { - fontFamily: expect.stringMatching( - /^'__Inter_.{6}', '__Inter_Fallback_.{6}'$/ - ), - fontWeight: 900, - fontStyle: 'normal', - }, - }) - expect(JSON.parse($('#comp-with-fonts-roboto').text())).toEqual({ - className: expect.stringMatching(getClassNameRegex('className')), - style: { - fontFamily: expect.stringMatching( - /^'__Roboto_.{6}', '__Roboto_Fallback_.{6}'$/ - ), - fontStyle: 'italic', - fontWeight: 100, - }, - }) - }) + test('google fonts with multiple weights/styles', async () => { + const html = await renderViaHTTP(next.url, '/with-google-fonts') + const $ = cheerio.load(html) - test('page with local fonts', async () => { - const html = await renderViaHTTP(next.url, '/with-local-fonts') - const $ = cheerio.load(html) - - // _app.js - expect(JSON.parse($('#app-open-sans').text())).toEqual({ - className: expect.stringMatching(getClassNameRegex('className')), - variable: expect.stringMatching(getClassNameRegex('variable')), - style: { - fontFamily: expect.stringMatching( - /^'__Open_Sans_.{6}', '__Open_Sans_Fallback_.{6}'$/ - ), - fontStyle: 'normal', - }, - }) - - // with-local-fonts.js - expect(JSON.parse($('#first-local-font').text())).toEqual({ - className: expect.stringMatching(getClassNameRegex('className')), - style: { - fontFamily: expect.stringMatching( - /^'__myFont1_.{6}', '__myFont1_Fallback_.{6}', system-ui$/ - ), - fontStyle: 'italic', - fontWeight: 100, - }, - }) - expect(JSON.parse($('#second-local-font').text())).toEqual({ - className: expect.stringMatching(getClassNameRegex('className')), - variable: expect.stringMatching(getClassNameRegex('variable')), - style: { - fontFamily: expect.stringMatching( - /^'__myFont2_.{6}', '__myFont2_Fallback_.{6}'$/ - ), - }, - }) - }) + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // Preload + expect($('link[as="font"]').length).toBe(8) + + const hrefs = Array.from($('link[as="font"]')) + .map((el) => el.attribs.href) + .sort() + + for (const href of hrefs) { + hrefMatchesFontWithSizeAdjust(href) + } - test('Variable font without weight range', async () => { - const html = await renderViaHTTP( - next.url, - '/variable-font-without-weight-range' - ) - const $ = cheerio.load(html) - - expect(JSON.parse($('#nabla').text())).toEqual({ - className: expect.stringMatching(getClassNameRegex('className')), - style: { - fontFamily: expect.stringMatching( - /^'__Nabla_.{6}', '__Nabla_Fallback_.{6}'$/ - ), - fontStyle: 'normal', - }, - }) + expect(hrefs.length).toBe(8) + }) + + test('font without preloadable subsets', async () => { + const html = await renderViaHTTP( + next.url, + '/font-without-preloadable-subsets' + ) + const $ = cheerio.load(html) + + // Preconnect + expect($('link[rel="preconnect"]').length).toBe(0) + + // From _app + expect($('link[as="font"]').length).toBe(1) + const attributes = $('link[as="font"]').get(0).attribs + + expect(attributes.as).toBe('font') + expect(attributes.crossorigin).toBe('anonymous') + hrefMatchesFontWithSizeAdjust(attributes.href) + expect(attributes.rel).toBe('preload') + expect(attributes.type).toBe('font/woff2') + expect(attributes['data-next-font']).toBe('size-adjust') + }) + + test('font without size adjust', async () => { + const html = await renderViaHTTP(next.url, '/with-fallback') + const $ = cheerio.load(html) + const links = Array.from($('link[as="font"]')) + .map((node) => node.attribs) + .sort((a, b) => { + return a.href.localeCompare(b.href) }) + const attributes = links[1] + expect(attributes.as).toBe('font') + expect(attributes.crossorigin).toBe('anonymous') + hrefMatchesFontWithoutSizeAdjust(attributes.href) + expect(attributes.rel).toBe('preload') + expect(attributes.type).toBe('font/woff2') + expect(attributes['data-next-font']).toBe('') + + const attributes2 = links[2] + + expect(attributes2.as).toBe('font') + expect(attributes2.crossorigin).toBe('anonymous') + hrefMatchesFontWithoutSizeAdjust(attributes2.href) + expect(attributes2.rel).toBe('preload') + expect(attributes2.type).toBe('font/woff2') + expect(attributes2['data-next-font']).toBe('') + }) + }) + + describe('Fallback fontfaces', () => { + describe('local', () => { + test('Indie flower', async () => { + const browser = await webdriver(next.url, '/with-local-fonts') + + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('103.26%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('51.94%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('94%') }) - describe('computed styles', () => { - test('page with fonts', async () => { - const browser = await webdriver(next.url, '/with-fonts') - - // _app.js - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#app-open-sans")).fontFamily' - ) - ).toMatch(/^__Open_Sans_.{6}, __Open_Sans_Fallback_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#app-open-sans")).fontWeight' - ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#app-open-sans")).fontStyle' - ) - ).toBe('normal') - - // with-fonts.js - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontFamily' - ) - ).toMatch(/^__Open_Sans_.{6}, __Open_Sans_Fallback_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontWeight' - ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fonts-open-sans")).fontStyle' - ) - ).toBe('normal') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fonts-open-sans-style")).fontWeight' - ) - ).toBe('400') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fonts-open-sans-style")).fontStyle' - ) - ).toBe('normal') - - // CompWithFonts.js - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontFamily' - ) - ).toMatch(/^__Inter_.{6}, __Inter_Fallback_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontWeight' - ) - ).toBe('900') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-inter")).fontStyle' - ) - ).toBe('normal') - - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontFamily' - ) - ).toMatch(/^__Roboto_.{6}, __Roboto_Fallback_.{6}$/) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontWeight' - ) - ).toBe('100') - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#comp-with-fonts-roboto")).fontStyle' - ) - ).toBe('italic') - }) + test('Fraunces', async () => { + const browser = await webdriver(next.url, '/with-local-fonts') - test('page using variables', async () => { - const browser = await webdriver(next.url, '/variables') - - // Fira Code Variable - const firaCodeRegex = /^__Fira_Code_.{6}, __Fira_Code_Fallback_.{6}$/ - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#variables-fira-code")).fontFamily' - ) - ).toMatch(firaCodeRegex) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#without-variables-fira-code")).fontFamily' - ) - ).not.toMatch(firaCodeRegex) - - // Roboto 100 Italic - const roboto100ItalicRegex = /^__Roboto_.{6}, __Roboto_Fallback_.{6}$/ - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#variables-roboto-100-italic")).fontFamily' - ) - ).toMatch(roboto100ItalicRegex) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#without-variables-roboto-100-italic")).fontFamily' - ) - ).not.toMatch(roboto100ItalicRegex) - - // Local font - const localFontRegex = /^__myFont_.{6}, __myFont_Fallback_.{6}$/ - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#variables-local-font")).fontFamily' - ) - ).toMatch(localFontRegex) - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#without-variables-local-font")).fontFamily' - ) - ).not.toMatch(localFontRegex) - }) + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('84.71%') - test('page using fallback fonts', async () => { - const browser = await webdriver(next.url, '/with-fallback') - - // .className - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fallback-fonts-classname")).fontFamily' - ) - ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) - - // .style - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fallback-fonts-style")).fontFamily' - ) - ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) - - // .variable - expect( - await browser.eval( - 'getComputedStyle(document.querySelector("#with-fallback-fonts-variable")).fontFamily' - ) - ).toMatch(/^__Open_Sans_.{6}, system-ui, Arial$/) - }) + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('22.09%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('115.45%') }) - describe('preload', () => { - test('page with fonts', async () => { - const html = await renderViaHTTP(next.url, '/with-fonts') - const $ = cheerio.load(html) - - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - expect($('link[as="font"]').length).toBe(2) - const links = Array.from($('link[as="font"]')).sort((a, b) => { - return a.attribs.href.localeCompare(b.attribs.href) - }) - // From /_app - const attributes = links[0].attribs - expect(attributes.as).toBe('font') - expect(attributes.crossorigin).toBe('anonymous') - hrefMatchesFontWithSizeAdjust(attributes.href) - expect(attributes.rel).toBe('preload') - expect(attributes.type).toBe('font/woff2') - expect(attributes['data-next-font']).toBe('size-adjust') - - const attributes2 = links[1].attribs - expect(attributes2.as).toBe('font') - expect(attributes2.crossorigin).toBe('anonymous') - hrefMatchesFontWithSizeAdjust(attributes2.href) - expect(attributes2.rel).toBe('preload') - expect(attributes2.type).toBe('font/woff2') - expect(attributes2['data-next-font']).toBe('size-adjust') - }) + test('Roboto multiple weights and styles', async () => { + const browser = await webdriver(next.url, '/with-local-fonts') - test('page without fonts', async () => { - const html = await renderViaHTTP(next.url, '/without-fonts') - const $ = cheerio.load(html) + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('92.49%') - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('24.34%') - // From _app - expect($('link[as="font"]').length).toBe(1) + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') - const attributes = $('link[as="font"]').get(0).attribs - expect(attributes.as).toBe('font') - expect(attributes.crossorigin).toBe('anonymous') - hrefMatchesFontWithSizeAdjust(attributes.href) - expect(attributes.rel).toBe('preload') - expect(attributes.type).toBe('font/woff2') - expect(attributes['data-next-font']).toBe('size-adjust') - }) + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('100.3%') + }) - test('page with local fonts', async () => { - const html = await renderViaHTTP(next.url, '/with-local-fonts') - const $ = cheerio.load(html) - - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // Preload - expect($('link[as="font"]').length).toBe(5) - const hrefs = Array.from($('link[as="font"]')) - .map((el) => el.attribs.href) - .sort() - for (const href of hrefs) { - hrefMatchesFontWithSizeAdjust(href) - } - expect(hrefs.length).toBe(5) - }) + test('Roboto multiple weights and styles - variable 1', async () => { + const browser = await webdriver(next.url, '/with-local-fonts') - test('google fonts with multiple weights/styles', async () => { - const html = await renderViaHTTP(next.url, '/with-google-fonts') - const $ = cheerio.load(html) + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('92.49%') - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('24.34%') - // Preload - expect($('link[as="font"]').length).toBe(8) + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') - const hrefs = Array.from($('link[as="font"]')) - .map((el) => el.attribs.href) - .sort() + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('100.3%') + }) - for (const href of hrefs) { - hrefMatchesFontWithSizeAdjust(href) - } + test('Roboto multiple weights and styles - variable 2', async () => { + const browser = await webdriver(next.url, '/with-local-fonts') - expect(hrefs.length).toBe(8) - }) + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('92.49%') - test('font without preloadable subsets', async () => { - const html = await renderViaHTTP( - next.url, - '/font-without-preloadable-subsets' - ) - const $ = cheerio.load(html) - - // Preconnect - expect($('link[rel="preconnect"]').length).toBe(0) - - // From _app - expect($('link[as="font"]').length).toBe(1) - const attributes = $('link[as="font"]').get(0).attribs - - expect(attributes.as).toBe('font') - expect(attributes.crossorigin).toBe('anonymous') - hrefMatchesFontWithSizeAdjust(attributes.href) - expect(attributes.rel).toBe('preload') - expect(attributes.type).toBe('font/woff2') - expect(attributes['data-next-font']).toBe('size-adjust') - }) + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('24.34%') - test('font without size adjust', async () => { - const html = await renderViaHTTP(next.url, '/with-fallback') - const $ = cheerio.load(html) - const links = Array.from($('link[as="font"]')) - .map((node) => node.attribs) - .sort((a, b) => { - return a.href.localeCompare(b.href) - }) - const attributes = links[1] - expect(attributes.as).toBe('font') - expect(attributes.crossorigin).toBe('anonymous') - hrefMatchesFontWithoutSizeAdjust(attributes.href) - expect(attributes.rel).toBe('preload') - expect(attributes.type).toBe('font/woff2') - expect(attributes['data-next-font']).toBe('') - - const attributes2 = links[2] - - expect(attributes2.as).toBe('font') - expect(attributes2.crossorigin).toBe('anonymous') - hrefMatchesFontWithoutSizeAdjust(attributes2.href) - expect(attributes2.rel).toBe('preload') - expect(attributes2.type).toBe('font/woff2') - expect(attributes2['data-next-font']).toBe('') - }) + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('100.3%') }) + }) - describe('Fallback fontfaces', () => { - describe('local', () => { - test('Indie flower', async () => { - const browser = await webdriver(next.url, '/with-local-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('103.26%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('51.94%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont2_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('94%') - }) - - test('Fraunces', async () => { - const browser = await webdriver(next.url, '/with-local-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('84.71%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('22.09%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("myFont1_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('115.45%') - }) - - test('Roboto multiple weights and styles', async () => { - const browser = await webdriver(next.url, '/with-local-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('92.49%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('24.34%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("roboto_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('100.3%') - }) - - test('Roboto multiple weights and styles - variable 1', async () => { - const browser = await webdriver(next.url, '/with-local-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('92.49%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('24.34%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar1_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('100.3%') - }) - - test('Roboto multiple weights and styles - variable 2', async () => { - const browser = await webdriver(next.url, '/with-local-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('92.49%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('24.34%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("robotoVar2_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('100.3%') - }) - }) + describe('google', () => { + test('Indie flower', async () => { + const browser = await webdriver(next.url, '/with-google-fonts') + + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('103.05%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('51.84%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('94.19%') + }) - describe('google', () => { - test('Indie flower', async () => { - const browser = await webdriver(next.url, '/with-google-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('103.05%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('51.84%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Indie_Flower_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('94.19%') - }) - - test('Fraunces', async () => { - const browser = await webdriver(next.url, '/with-google-fonts') - - const ascentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).ascentOverride' - ) - expect(ascentOverride).toBe('84.71%') - - const descentOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).descentOverride' - ) - expect(descentOverride).toBe('22.09%') - - const lineGapOverride = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).lineGapOverride' - ) - expect(lineGapOverride).toBe('0%') - - const sizeAdjust = await browser.eval( - 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).sizeAdjust' - ) - expect(sizeAdjust).toBe('115.45%') - }) - }) + test('Fraunces', async () => { + const browser = await webdriver(next.url, '/with-google-fonts') + + const ascentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).ascentOverride' + ) + expect(ascentOverride).toBe('84.71%') + + const descentOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).descentOverride' + ) + expect(descentOverride).toBe('22.09%') + + const lineGapOverride = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).lineGapOverride' + ) + expect(lineGapOverride).toBe('0%') + + const sizeAdjust = await browser.eval( + 'Array.from(document.fonts.values()).find(font => font.family.includes("Fraunces_Fallback")).sizeAdjust' + ) + expect(sizeAdjust).toBe('115.45%') }) }) - } + }) }) diff --git a/test/e2e/next-font/with-proxy.test.ts b/test/e2e/next-font/with-proxy.test.ts index da1a5dea5d451..1f41d78d9d4dd 100644 --- a/test/e2e/next-font/with-proxy.test.ts +++ b/test/e2e/next-font/with-proxy.test.ts @@ -30,8 +30,8 @@ describe('next/font/google with proxy', () => { next = await createNext({ files: new FileRef(join(__dirname, 'with-proxy')), dependencies: { - react: 'latest', - 'react-dom': 'latest', + react: '19.0.0-beta-4508873393-20240430', + 'react-dom': '19.0.0-beta-4508873393-20240430', }, env: { http_proxy: 'http://localhost:' + PROXY_PORT, diff --git a/test/e2e/next-script/index.test.ts b/test/e2e/next-script/index.test.ts index 8e92e7a7d3ca3..a90d6083fe76d 100644 --- a/test/e2e/next-script/index.test.ts +++ b/test/e2e/next-script/index.test.ts @@ -41,8 +41,8 @@ describe('beforeInteractive in document Head', () => { `, }, dependencies: { - react: 'latest', - 'react-dom': 'latest', + react: '19.0.0-beta-4508873393-20240430', + 'react-dom': '19.0.0-beta-4508873393-20240430', }, }) }) @@ -101,8 +101,8 @@ describe('beforeInteractive in document body', () => { `, }, dependencies: { - react: 'latest', - 'react-dom': 'latest', + react: '19.0.0-beta-4508873393-20240430', + 'react-dom': '19.0.0-beta-4508873393-20240430', }, }) }) @@ -150,8 +150,8 @@ describe('beforeInteractive in document body', () => { }, // TODO: @housseindjirdeh: verify React 18 functionality dependencies: { - react: 'latest', - 'react-dom': 'latest', + react: '19.0.0-beta-4508873393-20240430', + 'react-dom': '19.0.0-beta-4508873393-20240430', }, }) }) @@ -201,8 +201,8 @@ describe('beforeInteractive in document body', () => { `, }, dependencies: { - react: 'latest', - 'react-dom': 'latest', + react: '19.0.0-beta-4508873393-20240430', + 'react-dom': '19.0.0-beta-4508873393-20240430', '@builder.io/partytown': '0.4.2', }, }) @@ -290,8 +290,8 @@ describe('beforeInteractive in document body', () => { `, }, dependencies: { - react: 'latest', - 'react-dom': 'latest', + react: '19.0.0-beta-4508873393-20240430', + 'react-dom': '19.0.0-beta-4508873393-20240430', '@builder.io/partytown': '0.4.2', }, }) @@ -406,8 +406,8 @@ describe('beforeInteractive in document body', () => { }, dependencies: { '@builder.io/partytown': '0.4.2', - react: 'latest', - 'react-dom': 'latest', + react: '19.0.0-beta-4508873393-20240430', + 'react-dom': '19.0.0-beta-4508873393-20240430', }, }) }) diff --git a/test/e2e/next-test/first-time-setup-js/package.json b/test/e2e/next-test/first-time-setup-js/package.json index c873cfd75fed1..e0996207ccd63 100644 --- a/test/e2e/next-test/first-time-setup-js/package.json +++ b/test/e2e/next-test/first-time-setup-js/package.json @@ -8,7 +8,7 @@ }, "dependencies": { "next": "canary", - "react": "^18", - "react-dom": "^18" + "react": "19.0.0-beta-4508873393-20240430", + "react-dom": "19.0.0-beta-4508873393-20240430" } } diff --git a/test/e2e/next-test/first-time-setup-ts/package.json b/test/e2e/next-test/first-time-setup-ts/package.json index f1d2c0f255c54..86fc8d78a5962 100644 --- a/test/e2e/next-test/first-time-setup-ts/package.json +++ b/test/e2e/next-test/first-time-setup-ts/package.json @@ -8,8 +8,8 @@ }, "dependencies": { "next": "canary", - "react": "^18", - "react-dom": "^18" + "react": "19.0.0-beta-4508873393-20240430", + "react-dom": "19.0.0-beta-4508873393-20240430" }, "devDependencies": { "@types/react": "^18", diff --git a/test/e2e/next-test/next-test.test.ts b/test/e2e/next-test/next-test.test.ts index fe80469faae0a..718221be73101 100644 --- a/test/e2e/next-test/next-test.test.ts +++ b/test/e2e/next-test/next-test.test.ts @@ -91,7 +91,8 @@ describe('next test', () => { }) }) - it('should execute playwright tests', async () => { + // TODO: fix the playwright download issue + it.skip('should execute playwright tests', async () => { const { stdout } = spawnSync('pnpm', ['next', 'experimental-test'], { cwd: basicExample.testDir, encoding: 'utf-8', diff --git a/test/e2e/nonce-head-manager/app/pages/csp.js b/test/e2e/nonce-head-manager/app/pages/csp.js index b2cf71cad2439..c35c29ac4bc15 100644 --- a/test/e2e/nonce-head-manager/app/pages/csp.js +++ b/test/e2e/nonce-head-manager/app/pages/csp.js @@ -1,20 +1,33 @@ import React from 'react' -import Head from 'next/head' +import Script from 'next/script' const Page = () => { const [counter, setCounter] = React.useState(0) - const [useSrc1, setUseSrc1] = React.useState(true) + const [scriptURL, toggleScriptSource] = React.useReducer( + (currentScriptURL, id) => { + const scriptSource = + typeof currentScriptURL === 'string' + ? currentScriptURL + : currentScriptURL.pathname + if (scriptSource === '/src-1.js') { + return new URL(`/src-2.js?key=${Math.random()}`, window.location) + } else { + return new URL(`/src-1.js?key=${Math.random()}`, window.location) + } + }, + '/src-1.js' + ) + const scriptSource = + typeof scriptURL === 'string' ? scriptURL : scriptURL.href return ( <> - -
) } diff --git a/test/production/pages-dir/production/test/index.test.ts b/test/production/pages-dir/production/test/index.test.ts index 5b6e60035e789..5304fa9ef0aad 100644 --- a/test/production/pages-dir/production/test/index.test.ts +++ b/test/production/pages-dir/production/test/index.test.ts @@ -181,7 +181,7 @@ describe('Production Usage', () => { /webpack-runtime\.js/, /node_modules\/react\/index\.js/, /node_modules\/react\/package\.json/, - /node_modules\/react\/cjs\/react\.production\.min\.js/, + /node_modules\/react\/cjs\/react\.production\.js/, ], notTests: [/\0/, /\?/, /!/], }, @@ -192,7 +192,7 @@ describe('Production Usage', () => { /chunks\/.*?\.js/, /node_modules\/react\/index\.js/, /node_modules\/react\/package\.json/, - /node_modules\/react\/cjs\/react\.production\.min\.js/, + /node_modules\/react\/cjs\/react\.production\.js/, /node_modules\/next/, ], notTests: [/\0/, /\?/, /!/], @@ -204,7 +204,7 @@ describe('Production Usage', () => { /chunks\/.*?\.js/, /node_modules\/react\/index\.js/, /node_modules\/react\/package\.json/, - /node_modules\/react\/cjs\/react\.production\.min\.js/, + /node_modules\/react\/cjs\/react\.production\.js/, /node_modules\/next/, /node_modules\/nanoid\/index\.js/, /node_modules\/nanoid\/url-alphabet\/index\.js/, @@ -219,7 +219,7 @@ describe('Production Usage', () => { /chunks\/.*?\.js/, /node_modules\/react\/index\.js/, /node_modules\/react\/package\.json/, - /node_modules\/react\/cjs\/react\.production\.min\.js/, + /node_modules\/react\/cjs\/react\.production\.js/, /node_modules\/next/, ], notTests: [ @@ -1033,12 +1033,9 @@ describe('Production Usage', () => { it('should not put backslashes in pages-manifest.json', () => { // Whatever platform you build on, pages-manifest.json should use forward slash (/) // See: https://github.com/vercel/next.js/issues/4920 - const pagesManifest = require(join( - next.testDir, - '.next', - 'server', - PAGES_MANIFEST - )) + const pagesManifest = require( + join(next.testDir, '.next', 'server', PAGES_MANIFEST) + ) for (let key of Object.keys(pagesManifest)) { expect(key).not.toMatch(/\\/) diff --git a/test/production/standalone-mode/required-server-files/required-server-files-app.test.ts b/test/production/standalone-mode/required-server-files/required-server-files-app.test.ts index 0860282fb7cf1..410fa183b3f1b 100644 --- a/test/production/standalone-mode/required-server-files/required-server-files-app.test.ts +++ b/test/production/standalone-mode/required-server-files/required-server-files-app.test.ts @@ -72,9 +72,10 @@ describe('required server files app router', () => { const testServer = join(next.testDir, 'standalone/server.js') await fs.writeFile( testServer, - ( - await fs.readFile(testServer, 'utf8') - ).replace('port:', `minimalMode: ${minimalMode},port:`) + (await fs.readFile(testServer, 'utf8')).replace( + 'port:', + `minimalMode: ${minimalMode},port:` + ) ) appPort = await findPort() server = await initNextServerScript( diff --git a/test/production/standalone-mode/required-server-files/required-server-files-i18n.test.ts b/test/production/standalone-mode/required-server-files/required-server-files-i18n.test.ts index 820d81b6ffb95..12da3649353d7 100644 --- a/test/production/standalone-mode/required-server-files/required-server-files-i18n.test.ts +++ b/test/production/standalone-mode/required-server-files/required-server-files-i18n.test.ts @@ -106,9 +106,10 @@ describe('required server files i18n', () => { const testServer = join(next.testDir, 'standalone/server.js') await fs.writeFile( testServer, - ( - await fs.readFile(testServer, 'utf8') - ).replace('port:', 'minimalMode: true,port:') + (await fs.readFile(testServer, 'utf8')).replace( + 'port:', + 'minimalMode: true,port:' + ) ) appPort = await findPort() server = await initNextServerScript( diff --git a/test/production/standalone-mode/required-server-files/required-server-files-ppr.test.ts b/test/production/standalone-mode/required-server-files/required-server-files-ppr.test.ts index e125319491f63..f7501015d73e0 100644 --- a/test/production/standalone-mode/required-server-files/required-server-files-ppr.test.ts +++ b/test/production/standalone-mode/required-server-files/required-server-files-ppr.test.ts @@ -82,9 +82,10 @@ describe('required server files app router', () => { const testServer = join(next.testDir, 'standalone/server.js') await fs.writeFile( testServer, - ( - await fs.readFile(testServer, 'utf8') - ).replace('port:', `minimalMode: ${minimalMode},port:`) + (await fs.readFile(testServer, 'utf8')).replace( + 'port:', + `minimalMode: ${minimalMode},port:` + ) ) appPort = await findPort() server = await initNextServerScript( diff --git a/test/production/standalone-mode/required-server-files/required-server-files.test.ts b/test/production/standalone-mode/required-server-files/required-server-files.test.ts index d595ff289569d..7d5d33a3bb079 100644 --- a/test/production/standalone-mode/required-server-files/required-server-files.test.ts +++ b/test/production/standalone-mode/required-server-files/required-server-files.test.ts @@ -111,9 +111,10 @@ describe('required server files', () => { const testServer = join(next.testDir, 'standalone/server.js') await fs.writeFile( testServer, - ( - await fs.readFile(testServer, 'utf8') - ).replace('port:', `minimalMode: ${minimalMode},port:`) + (await fs.readFile(testServer, 'utf8')).replace( + 'port:', + `minimalMode: ${minimalMode},port:` + ) ) appPort = await findPort() server = await initNextServerScript( @@ -1289,9 +1290,10 @@ describe('required server files', () => { const testServer = join(standaloneDir, 'server.js') await fs.writeFile( testServer, - ( - await fs.readFile(testServer, 'utf8') - ).replace('minimalMode: true', 'minimalMode: false') + (await fs.readFile(testServer, 'utf8')).replace( + 'minimalMode: true', + 'minimalMode: false' + ) ) appPort = await findPort() server = await initNextServerScript( diff --git a/test/turbopack-build-tests-manifest.json b/test/turbopack-build-tests-manifest.json index 38e08bbbba840..37ef5d7fde5cf 100644 --- a/test/turbopack-build-tests-manifest.json +++ b/test/turbopack-build-tests-manifest.json @@ -95,10 +95,10 @@ "test/e2e/app-dir/actions/app-action-form-state.test.ts": { "passed": [], "failed": [ - "app-dir action useFormState should send the action to the provided permalink with form state when JS disabled", - "app-dir action useFormState should support hydrating the app from progressively enhanced form request", - "app-dir action useFormState should support submitting form state with JS", - "app-dir action useFormState should support submitting form state without JS" + "app-dir action useActionState should send the action to the provided permalink with form state when JS disabled", + "app-dir action useActionState should support hydrating the app from progressively enhanced form request", + "app-dir action useActionState should support submitting form state with JS", + "app-dir action useActionState should support submitting form state without JS" ], "pending": [], "flakey": [], @@ -1001,7 +1001,6 @@ "app dir - basic server components should serve client component should serve client-side", "app dir - basic server components should serve client component should serve server-side", "app dir - basic server components should serve shared component", - "app dir - basic should encode chunk path correctly", "app dir - basic should ensure the suffix is at the end of the stream", "app dir - basic should generate build traces correctly", "app dir - basic should handle hash in initial url", @@ -1030,7 +1029,6 @@ "app dir - basic should serve from public", "app dir - basic should serve nested parent", "app dir - basic should serve page as a segment name correctly", - "app dir - basic should serve polyfills for browsers that do not support modules", "app dir - basic should successfully detect app route during prefetch", "app dir - basic should use new root layout when provided", "app dir - basic should use text/x-component for flight", @@ -1039,7 +1037,10 @@ "app dir - basic template component should render the template that holds state in a client component and reset on navigation", "app dir - basic template component should render the template that is a server component and rerender on navigation" ], - "failed": [], + "failed": [ + "app dir - basic should encode chunk path correctly", + "app dir - basic should serve polyfills for browsers that do not support modules" + ], "pending": [ "app dir - basic should soft replace", "app dir - basic known bugs should support React fetch instrumentation client component", @@ -1090,6 +1091,7 @@ "app dir - basic next/script should insert preload tags for beforeInteractive and afterInteractive scripts", "app dir - basic next/script should load stylesheets for next/scripts", "app dir - basic next/script should pass `nonce`", + "app dir - basic next/script should pass nonce when using next/font", "app dir - basic next/script should pass on extra props for beforeInteractive scripts with a src prop", "app dir - basic next/script should pass on extra props for beforeInteractive scripts without a src prop", "app dir - basic next/script should support next/script and render in correct order", @@ -1870,14 +1872,12 @@ "failed": [ "app dir - metadata dynamic routes icon image routes should render apple icon with dynamic routes", "app dir - metadata dynamic routes icon image routes should render icon with dynamic routes", - "app dir - metadata dynamic routes route segment config should generate dynamic route if dynamic config is force-dynamic", - "app dir - metadata dynamic routes should generate static paths of dynamic sitemap in production", + "app dir - metadata dynamic routes should error if the default export of dynamic image is missing", + "app dir - metadata dynamic routes should error when id is missing in generateImageMetadata", + "app dir - metadata dynamic routes should error when id is missing in generateSitemaps", "app dir - metadata dynamic routes should generate unique path for image routes under group routes", - "app dir - metadata dynamic routes should include default og font files in file trace", "app dir - metadata dynamic routes should inject dynamic metadata properly to head", - "app dir - metadata dynamic routes should optimize routes without multiple generation API as static routes", "app dir - metadata dynamic routes should pick configured metadataBase instead of deployment url for canonical url", - "app dir - metadata dynamic routes should support edge runtime of image routes", "app dir - metadata dynamic routes should use localhost for local prod and fallback to deployment url when metadataBase is falsy", "app dir - metadata dynamic routes social image routes should fill params into dynamic routes url of metadata images", "app dir - metadata dynamic routes social image routes should fill params into routes groups url of static images", @@ -1885,13 +1885,19 @@ "app dir - metadata dynamic routes social image routes should handle manifest.[ext] dynamic routes", "app dir - metadata dynamic routes social image routes should render og image with opengraph-image dynamic routes", "app dir - metadata dynamic routes social image routes should render og image with twitter-image dynamic routes", - "app dir - metadata dynamic routes social image routes should support generate multi images with generateImageMetadata", - "app dir - metadata dynamic routes social image routes should support generate multi sitemaps with generateSitemaps", "app dir - metadata dynamic routes social image routes should support params as argument in dynamic routes", - "app dir - metadata dynamic routes text routes should handle robots.[ext] dynamic routes", - "app dir - metadata dynamic routes text routes should handle sitemap.[ext] dynamic routes", - "app dir - metadata dynamic routes text routes should not throw if client components are imported but not used", - "app dir - metadata dynamic routes text routes should support alternate.languages in sitemap" + "app dir - metadata dynamic routes social image routes should support generate multi images with generateImageMetadata", + "app dir - metadata dynamic routes robots.txt should handle robots.[ext] dynamic routes", + "app dir - metadata dynamic routes should support edge runtime of image routes", + "app dir - metadata dynamic routes should include default og font files in file trace", + "app dir - metadata dynamic routes route segment config should generate dynamic route if dynamic config is force-dynamic", + "app dir - metadata dynamic routes sitemap should not throw if client components are imported but not used in sitemap", + "app dir - metadata dynamic routes sitemap should handle sitemap.[ext] dynamic routes", + "app dir - metadata dynamic routes sitemap social image routes should support generate multi sitemaps with generateSitemaps", + "app dir - metadata dynamic routes sitemap should support alternate.languages in sitemap", + "app dir - metadata dynamic routes sitemap should support generate multi sitemaps with generateSitemaps", + "app dir - metadata dynamic routes sitemap should optimize routes without multiple generation API as static routes", + "app dir - metadata dynamic routes sitemap should generate static paths of dynamic sitemap in production" ], "pending": [], "flakey": [], @@ -2091,22 +2097,22 @@ }, "test/e2e/app-dir/next-font/next-font.test.ts": { "passed": [ - "app dir - next/font app app dir - next-font computed styles should have correct styles at /", - "app dir - next/font app app dir - next-font computed styles should have correct styles at /client", - "app dir - next/font app app dir - next-font import values should have correct values at /", - "app dir - next/font app app dir - next-font import values should have correct values at /client", - "app dir - next/font app app dir - next-font import values should transform code in node_modules", - "app dir - next/font app app dir - next-font navigation should not have duplicate preload tags on navigation", - "app dir - next/font app app dir - next-font preconnect should add preconnect when preloading is disabled in component", - "app dir - next/font app app dir - next-font preconnect should add preconnect when preloading is disabled in layout", - "app dir - next/font app app dir - next-font preconnect should not preconnect when css is used but no fonts", - "app dir - next/font app app dir - next-font preload should preload correctly with client components", - "app dir - next/font app app dir - next-font preload should preload correctly with layout using fonts", - "app dir - next/font app app dir - next-font preload should preload correctly with page using fonts" + "app dir - next/font app dir - next-font computed styles should have correct styles at /", + "app dir - next/font app dir - next-font computed styles should have correct styles at /client", + "app dir - next/font app dir - next-font import values should have correct values at /", + "app dir - next/font app dir - next-font import values should have correct values at /client", + "app dir - next/font app dir - next-font import values should transform code in node_modules", + "app dir - next/font app dir - next-font navigation should not have duplicate preload tags on navigation", + "app dir - next/font app dir - next-font preconnect should add preconnect when preloading is disabled in component", + "app dir - next/font app dir - next-font preconnect should add preconnect when preloading is disabled in layout", + "app dir - next/font app dir - next-font preconnect should not preconnect when css is used but no fonts", + "app dir - next/font app dir - next-font preload should preload correctly with client components", + "app dir - next/font app dir - next-font preload should preload correctly with layout using fonts", + "app dir - next/font app dir - next-font preload should preload correctly with page using fonts" ], "failed": [ - "app dir - next/font app app dir - next-font preconnect should add preconnect when preloading is disabled in page", - "app dir - next/font app app dir - next-font preload should preload correctly with server components" + "app dir - next/font app dir - next-font preconnect should add preconnect when preloading is disabled in page", + "app dir - next/font app dir - next-font preload should preload correctly with server components" ], "pending": [], "flakey": [], @@ -3282,8 +3288,8 @@ }, "test/e2e/app-dir/server-components-externals/index.test.ts": { "passed": [ - "app-dir - server components externals should externalize serverComponentsExternalPackages for server rendering layer", - "app-dir - server components externals should have externals for those in config.experimental.serverComponentsExternalPackages", + "app-dir - server components externals should externalize serverExternalPackages for server rendering layer", + "app-dir - server components externals should have externals for those in config.serverExternalPackages", "app-dir - server components externals uses externals for predefined list in server-external-packages.json" ], "failed": [], @@ -8478,11 +8484,11 @@ "runtimeError": false }, "test/integration/externals-pages-bundle/test/index.test.js": { - "passed": [], - "failed": [ - "bundle pages externals with config.experimental.bundlePagesExternals production mode should have no externals with the config set", - "bundle pages externals with config.experimental.bundlePagesExternals production mode should respect the serverComponentsExternals config" + "passed": [ + "bundle pages externals with config.bundlePagesRouterDependencies production mode should have no externals with the config set", + "bundle pages externals with config.bundlePagesRouterDependencies production mode should respect the serverExternalPackages config" ], + "failed": [], "pending": [], "flakey": [], "runtimeError": false @@ -10842,12 +10848,133 @@ "with contentDispositionType attachment dev support with next.config.js should use cached image file when parameters are the same for animated gif" ], "failed": [ + "with contentDispositionType attachment Production Mode Server support w/o next.config.js should set cache-control to immutable for static images", "with contentDispositionType attachment Production Mode Server support with next.config.js should set cache-control to immutable for static images" ], "pending": [], "flakey": [], "runtimeError": false }, + "test/integration/image-optimizer/test/dangerously-allow-svg.test.ts": { + "passed": [ + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should automatically detect image type when content-type is octet-stream", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should compress avif smaller than webp at q=100", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should compress avif smaller than webp at q=50", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should compress avif smaller than webp at q=75", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should downlevel avif format to jpeg for old Safari", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should downlevel webp format to jpeg for old Safari", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should emit blur svg when width is 8 in dev but not prod", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should emit blur svg when width is less than 8 in dev but not prod", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should error if the image file does not exist", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should error if the resource isn't a valid image", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when domain is not defined in next.config.js", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when internal url is not an image", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when q is greater than 100", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when q is less than 1", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when q is missing", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when q is not a number", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when url fails to load an image", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when url has file protocol", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when url has ftp protocol", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when url is missing", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when w is 0", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when w is less than 0", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when w is missing", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when w is not a number", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when width is not in next.config.js", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should handle concurrent requests", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should handle non-ascii characters in image url", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain animated gif", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain animated png", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain animated png 2", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain animated webp", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain bmp", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain ico format", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain jpg format for old Safari", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain png format for old Safari", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should normalize invalid status codes", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should not allow svg with application header", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should not allow svg with comma header", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should not allow svg with uppercase header", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should not allow vector svg", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should not resize if requested width is larger than original source image", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize absolute url from localhost", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize relative url and new Chrome accept header as avif", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize relative url and old Chrome accept header as webp", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize relative url and png accept header", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize relative url and webp Firefox accept header", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize relative url with invalid accept header as gif", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize relative url with invalid accept header as png", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize relative url with invalid accept header as tiff", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should return home page", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should set 304 status without body when etag matches if-none-match", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should use cache and stale-while-revalidate when query is the same for external image", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should use cache and stale-while-revalidate when query is the same for internal image", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should use cached image file when parameters are the same for animated gif", + "with dangerouslyAllowSVG config dev support with next.config.js should automatically detect image type when content-type is octet-stream", + "with dangerouslyAllowSVG config dev support with next.config.js should compress avif smaller than webp at q=100", + "with dangerouslyAllowSVG config dev support with next.config.js should compress avif smaller than webp at q=50", + "with dangerouslyAllowSVG config dev support with next.config.js should compress avif smaller than webp at q=75", + "with dangerouslyAllowSVG config dev support with next.config.js should downlevel avif format to jpeg for old Safari", + "with dangerouslyAllowSVG config dev support with next.config.js should downlevel webp format to jpeg for old Safari", + "with dangerouslyAllowSVG config dev support with next.config.js should emit blur svg when width is 8 in dev but not prod", + "with dangerouslyAllowSVG config dev support with next.config.js should emit blur svg when width is less than 8 in dev but not prod", + "with dangerouslyAllowSVG config dev support with next.config.js should error if the image file does not exist", + "with dangerouslyAllowSVG config dev support with next.config.js should error if the resource isn't a valid image", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when domain is not defined in next.config.js", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when internal url is not an image", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when q is greater than 100", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when q is less than 1", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when q is missing", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when q is not a number", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when url fails to load an image", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when url has file protocol", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when url has ftp protocol", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when url is missing", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when w is 0", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when w is less than 0", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when w is missing", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when w is not a number", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when width is not in next.config.js", + "with dangerouslyAllowSVG config dev support with next.config.js should handle concurrent requests", + "with dangerouslyAllowSVG config dev support with next.config.js should handle non-ascii characters in image url", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain animated gif", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain animated png", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain animated png 2", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain animated webp", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain bmp", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain ico format", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain jpg format for old Safari", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain png format for old Safari", + "with dangerouslyAllowSVG config dev support with next.config.js should normalize invalid status codes", + "with dangerouslyAllowSVG config dev support with next.config.js should not allow svg with application header", + "with dangerouslyAllowSVG config dev support with next.config.js should not allow svg with comma header", + "with dangerouslyAllowSVG config dev support with next.config.js should not allow svg with uppercase header", + "with dangerouslyAllowSVG config dev support with next.config.js should not allow vector svg", + "with dangerouslyAllowSVG config dev support with next.config.js should not resize if requested width is larger than original source image", + "with dangerouslyAllowSVG config dev support with next.config.js should resize absolute url from localhost", + "with dangerouslyAllowSVG config dev support with next.config.js should resize relative url and new Chrome accept header as avif", + "with dangerouslyAllowSVG config dev support with next.config.js should resize relative url and old Chrome accept header as webp", + "with dangerouslyAllowSVG config dev support with next.config.js should resize relative url and png accept header", + "with dangerouslyAllowSVG config dev support with next.config.js should resize relative url and webp Firefox accept header", + "with dangerouslyAllowSVG config dev support with next.config.js should resize relative url with invalid accept header as gif", + "with dangerouslyAllowSVG config dev support with next.config.js should resize relative url with invalid accept header as png", + "with dangerouslyAllowSVG config dev support with next.config.js should resize relative url with invalid accept header as tiff", + "with dangerouslyAllowSVG config dev support with next.config.js should return home page", + "with dangerouslyAllowSVG config dev support with next.config.js should set 304 status without body when etag matches if-none-match", + "with dangerouslyAllowSVG config dev support with next.config.js should set cache-control to immutable for static images", + "with dangerouslyAllowSVG config dev support with next.config.js should use cache and stale-while-revalidate when query is the same for external image", + "with dangerouslyAllowSVG config dev support with next.config.js should use cache and stale-while-revalidate when query is the same for internal image", + "with dangerouslyAllowSVG config dev support with next.config.js should use cached image file when parameters are the same for animated gif" + ], + "failed": [ + "with dangerouslyAllowSVG config Production Mode Server support w/o next.config.js should set cache-control to immutable for static images", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should set cache-control to immutable for static images" + ], + "pending": [], + "flakey": [], + "runtimeError": false + }, "test/integration/image-optimizer/test/index.test.ts": { "passed": [ "Image Optimizer External rewrite support with for serving static content in images production mode should return response when image is served from an external rewrite", @@ -10995,6 +11122,7 @@ "with minimumCacheTTL of 5 sec dev support with next.config.js should use cached image file when parameters are the same for animated gif" ], "failed": [ + "with minimumCacheTTL of 5 sec Production Mode Server support w/o next.config.js should set cache-control to immutable for static images", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should set cache-control to immutable for static images" ], "pending": [], @@ -14305,6 +14433,13 @@ "flakey": [], "runtimeError": false }, + "test/production/deterministic-build/index.test.ts": { + "passed": [], + "failed": ["deterministic build should have same md5 file across build"], + "pending": [], + "flakey": [], + "runtimeError": false + }, "test/production/app-dir-edge-runtime-with-wasm/index.test.ts": { "passed": ["app-dir edge runtime with wasm should have built"], "failed": [], diff --git a/test/turbopack-dev-tests-manifest.json b/test/turbopack-dev-tests-manifest.json index 7aaf08045c8a8..44186cb43a69b 100644 --- a/test/turbopack-dev-tests-manifest.json +++ b/test/turbopack-dev-tests-manifest.json @@ -1096,15 +1096,6 @@ "flakey": [], "runtimeError": false }, - "test/development/acceptance-app/component-stack.test.ts": { - "passed": [ - "Component Stack in error overlay should show a component stack on hydration error" - ], - "failed": [], - "pending": [], - "flakey": [], - "runtimeError": false - }, "test/development/acceptance-app/dynamic-error.test.ts": { "passed": [ "dynamic = \"error\" in devmode should show error overlay when dynamic is forced" @@ -1205,11 +1196,11 @@ "Error overlay - RSC build errors should error when PureComponent from react is used in server component", "Error overlay - RSC build errors should error when createContext from react is used in server component", "Error overlay - RSC build errors should error when createFactory from react is used in server component", - "Error overlay - RSC build errors should error when findDOMNode from react-dom is used in server component", "Error overlay - RSC build errors should error when flushSync from react-dom is used in server component", "Error overlay - RSC build errors should error when page component export is not valid", "Error overlay - RSC build errors should error when page component export is not valid on initial load", "Error overlay - RSC build errors should error when unstable_batchedUpdates from react-dom is used in server component", + "Error overlay - RSC build errors should error when useActionState from react is used in server component", "Error overlay - RSC build errors should error when useDeferredValue from react is used in server component", "Error overlay - RSC build errors should error when useEffect from react is used in server component", "Error overlay - RSC build errors should error when useFormState from react-dom is used in server component", @@ -1433,15 +1424,6 @@ "flakey": [], "runtimeError": false }, - "test/development/acceptance/component-stack.test.ts": { - "passed": [ - "Component Stack in error overlay should show a component stack on hydration error" - ], - "failed": [], - "pending": [], - "flakey": [], - "runtimeError": false - }, "test/development/acceptance/error-recovery.test.ts": { "passed": [ "ReactRefreshLogBox turbo logbox: can recover from a component error", @@ -1576,9 +1558,9 @@ "runtimeError": false }, "test/development/app-dir/strict-mode-enabled-by-default/strict-mode-enabled-by-default.test.ts": { - "passed": ["Strict Mode enabled by default should work using browser"], + "passed": [], "failed": [], - "pending": [], + "pending": ["Strict Mode enabled by default should work using browser"], "flakey": [], "runtimeError": false }, @@ -2153,50 +2135,6 @@ }, "test/development/pages-dir/client-navigation/index.test.ts": { "passed": [ - "Client Navigation Rendering via HTTP 404 should 404 on not existent page", - "Client Navigation Rendering via HTTP 404 should 404 on wrong casing", - "Client Navigation Rendering via HTTP 404 should not 404 for /", - "Client Navigation Rendering via HTTP 404 should should not contain a page script in a 404 page", - "Client Navigation Rendering via HTTP allows to import .json files", - "Client Navigation Rendering via HTTP asPath", - "Client Navigation Rendering via HTTP default Content-Type", - "Client Navigation Rendering via HTTP default export is not a React Component", - "Client Navigation Rendering via HTTP error-in-the-global-scope", - "Client Navigation Rendering via HTTP error-inside-page", - "Client Navigation Rendering via HTTP getInitialProps circular structure", - "Client Navigation Rendering via HTTP getInitialProps resolves to null", - "Client Navigation Rendering via HTTP getInitialProps should be class method", - "Client Navigation Rendering via HTTP header helper avoids dedupe of meta tags with the same name if they use unique keys", - "Client Navigation Rendering via HTTP header helper avoids dedupe of specific tags", - "Client Navigation Rendering via HTTP header helper dedupes tags", - "Client Navigation Rendering via HTTP header helper dedupes tags with the same key as the default", - "Client Navigation Rendering via HTTP header helper renders Fragment children", - "Client Navigation Rendering via HTTP header helper renders boolean attributes correctly children", - "Client Navigation Rendering via HTTP header helper renders header information", - "Client Navigation Rendering via HTTP header renders default charset", - "Client Navigation Rendering via HTTP header renders default viewport", - "Client Navigation Rendering via HTTP renders a link component", - "Client Navigation Rendering via HTTP renders a stateless component", - "Client Navigation Rendering via HTTP renders properties populated asynchronously", - "Client Navigation Rendering via HTTP renders styled jsx", - "Client Navigation Rendering via HTTP renders styled jsx external", - "Client Navigation Rendering via HTTP renders when component is a forwardRef instance", - "Client Navigation Rendering via HTTP renders when component is a memo instance", - "Client Navigation Rendering via HTTP renders with fragment syntax", - "Client Navigation Rendering via HTTP setting Content-Type in getInitialProps", - "Client Navigation Rendering via HTTP should handle undefined prop in head server-side", - "Client Navigation Rendering via HTTP should place charset element at the top of ", - "Client Navigation Rendering via HTTP should render 404 for _next routes that do not exist", - "Client Navigation Rendering via HTTP should render page that has module.exports anywhere", - "Client Navigation Rendering via HTTP should render the page with `nextExport` property", - "Client Navigation Rendering via HTTP should render the page with custom extension", - "Client Navigation Rendering via HTTP should render the page without `err` property", - "Client Navigation Rendering via HTTP should render the page without `nextExport` property", - "Client Navigation Rendering via HTTP should set Cache-Control header", - "Client Navigation Rendering via HTTP should should not contain scripts that are not js", - "Client Navigation Rendering via HTTP should show a valid error when undefined is thrown", - "Client Navigation Rendering via HTTP with the HOC based router should include asPath", - "Client Navigation Rendering via HTTP with the HOC based router should navigate as expected", "Client Navigation foreign history manipulation should ignore foreign history state with missing properties", "Client Navigation foreign history manipulation should ignore history state with an invalid url", "Client Navigation foreign history manipulation should ignore history state without options", @@ -2206,8 +2144,6 @@ "Client Navigation runtime errors should show redbox when a client side error is thrown inside a component", "Client Navigation runtime errors should show redbox when a client side error is thrown outside a component", "Client Navigation should emit routeChangeError on hash change cancel", - "Client Navigation should handle boolean async prop in next/head client-side: false", - "Client Navigation should handle boolean async prop in next/head client-side: true", "Client Navigation should handle boolean async prop in next/script client-side: false", "Client Navigation should handle boolean async prop in next/script client-side: true", "Client Navigation should handle undefined prop in head client-side", @@ -2217,13 +2153,6 @@ "Client Navigation should only execute async and defer scripts with next/script once", "Client Navigation should scroll to top when the scroll option is set to true", "Client Navigation should work on nested /index/index.js", - "Client Navigation updating head while client routing should not warn when application/ld+json scripts are in head", - "Client Navigation updating head while client routing should only execute async and defer scripts once", - "Client Navigation updating head while client routing should update head during client routing", - "Client Navigation updating head while client routing should update head when unmounting component", - "Client Navigation updating head while client routing should update title during client routing", - "Client Navigation updating head while client routing should warn when scripts are in head", - "Client Navigation updating head while client routing should warn when stylesheets or scripts are in head", "Client Navigation with 404 pages should 404 on not existent page", "Client Navigation with 404 pages should 404 on wrong casing", "Client Navigation with 404 pages should 404 on wrong casing of url dynamic param", @@ -2296,7 +2225,88 @@ "Client Navigation with the same page but different querystring should navigate the page", "Client Navigation with the same page but different querystring should remove querystring", "Client Navigation with unexpected
nested tag should not redirect if passHref prop is not defined in Link", - "Client Navigation with unexpected nested tag should redirect if passHref prop is defined in Link" + "Client Navigation with unexpected nested tag should redirect if passHref prop is defined in Link", + "updating with strictNextHead=false while client routing should handle boolean async prop in next/head client-side: false", + "updating with strictNextHead=false while client routing should handle boolean async prop in next/head client-side: true", + "updating with strictNextHead=false while client routing should not warn when application/ld+json scripts are in head", + "updating with strictNextHead=false while client routing should only execute async and defer scripts once", + "updating with strictNextHead=false while client routing should update head during client routing", + "updating with strictNextHead=false while client routing should update head when unmounting component", + "updating with strictNextHead=false while client routing should update title during client routing", + "updating with strictNextHead=false while client routing should warn when scripts are in head", + "updating with strictNextHead=false while client routing should warn when stylesheets or scripts are in head", + "updating with strictNextHead=true while client routing should handle boolean async prop in next/head client-side: false", + "updating with strictNextHead=true while client routing should handle boolean async prop in next/head client-side: true", + "updating with strictNextHead=true while client routing should not warn when application/ld+json scripts are in head", + "updating with strictNextHead=true while client routing should only execute async and defer scripts once", + "updating with strictNextHead=true while client routing should update head during client routing", + "updating with strictNextHead=true while client routing should update head when unmounting component", + "updating with strictNextHead=true while client routing should update title during client routing", + "updating with strictNextHead=true while client routing should warn when scripts are in head", + "updating with strictNextHead=true while client routing should warn when stylesheets or scripts are in head" + ], + "failed": [], + "pending": [], + "flakey": [], + "runtimeError": false + }, + "test/development/pages-dir/client-navigation/rendering.test.ts": { + "passed": [ + "Client Navigation rendering with strictNextHead=false header helper avoids dedupe of meta tags with the same name if they use unique keys", + "Client Navigation rendering with strictNextHead=false header helper avoids dedupe of specific tags", + "Client Navigation rendering with strictNextHead=false header helper dedupes tags", + "Client Navigation rendering with strictNextHead=false header helper dedupes tags with the same key as the default", + "Client Navigation rendering with strictNextHead=false header helper renders Fragment children", + "Client Navigation rendering with strictNextHead=false header helper renders boolean attributes correctly children", + "Client Navigation rendering with strictNextHead=false header helper renders header information", + "Client Navigation rendering with strictNextHead=false header renders default charset", + "Client Navigation rendering with strictNextHead=false header renders default viewport", + "Client Navigation rendering with strictNextHead=false should handle undefined prop in head server-side", + "Client Navigation rendering with strictNextHead=false should place charset element at the top of ", + "Client Navigation rendering with strictNextHead=true header helper avoids dedupe of meta tags with the same name if they use unique keys", + "Client Navigation rendering with strictNextHead=true header helper avoids dedupe of specific tags", + "Client Navigation rendering with strictNextHead=true header helper dedupes tags", + "Client Navigation rendering with strictNextHead=true header helper dedupes tags with the same key as the default", + "Client Navigation rendering with strictNextHead=true header helper renders Fragment children", + "Client Navigation rendering with strictNextHead=true header helper renders boolean attributes correctly children", + "Client Navigation rendering with strictNextHead=true header helper renders header information", + "Client Navigation rendering with strictNextHead=true header renders default charset", + "Client Navigation rendering with strictNextHead=true header renders default viewport", + "Client Navigation rendering with strictNextHead=true should handle undefined prop in head server-side", + "Client Navigation rendering with strictNextHead=true should place charset element at the top of ", + "Client Navigation rendering Rendering via HTTP 404 should 404 on not existent page", + "Client Navigation rendering Rendering via HTTP 404 should 404 on wrong casing", + "Client Navigation rendering Rendering via HTTP 404 should not 404 for /", + "Client Navigation rendering Rendering via HTTP 404 should should not contain a page script in a 404 page", + "Client Navigation rendering Rendering via HTTP allows to import .json files", + "Client Navigation rendering Rendering via HTTP asPath", + "Client Navigation rendering Rendering via HTTP default Content-Type", + "Client Navigation rendering Rendering via HTTP default export is not a React Component", + "Client Navigation rendering Rendering via HTTP error-in-the-global-scope", + "Client Navigation rendering Rendering via HTTP error-inside-page", + "Client Navigation rendering Rendering via HTTP getInitialProps circular structure", + "Client Navigation rendering Rendering via HTTP getInitialProps resolves to null", + "Client Navigation rendering Rendering via HTTP getInitialProps should be class method", + "Client Navigation rendering Rendering via HTTP renders a link component", + "Client Navigation rendering Rendering via HTTP renders a stateless component", + "Client Navigation rendering Rendering via HTTP renders properties populated asynchronously", + "Client Navigation rendering Rendering via HTTP renders styled jsx", + "Client Navigation rendering Rendering via HTTP renders styled jsx external", + "Client Navigation rendering Rendering via HTTP renders when component is a forwardRef instance", + "Client Navigation rendering Rendering via HTTP renders when component is a memo instance", + "Client Navigation rendering Rendering via HTTP renders with fragment syntax", + "Client Navigation rendering Rendering via HTTP setting Content-Type in getInitialProps", + "Client Navigation rendering Rendering via HTTP should render 404 for _next routes that do not exist", + "Client Navigation rendering Rendering via HTTP should render page that has module.exports anywhere", + "Client Navigation rendering Rendering via HTTP should render the page with `nextExport` property", + "Client Navigation rendering Rendering via HTTP should render the page with custom extension", + "Client Navigation rendering Rendering via HTTP should render the page without `err` property", + "Client Navigation rendering Rendering via HTTP should render the page without `nextExport` property", + "Client Navigation rendering Rendering via HTTP should set Cache-Control header", + "Client Navigation rendering Rendering via HTTP should should not contain scripts that are not js", + "Client Navigation rendering Rendering via HTTP should show a valid error when undefined is thrown", + "Client Navigation rendering Rendering via HTTP with the HOC based router should include asPath", + "Client Navigation rendering Rendering via HTTP with the HOC based router should navigate as expected" ], "failed": [], "pending": [], @@ -2454,10 +2464,10 @@ }, "test/e2e/app-dir/actions/app-action-form-state.test.ts": { "passed": [ - "app-dir action useFormState should send the action to the provided permalink with form state when JS disabled", - "app-dir action useFormState should support hydrating the app from progressively enhanced form request", - "app-dir action useFormState should support submitting form state with JS", - "app-dir action useFormState should support submitting form state without JS" + "app-dir action useActionState should send the action to the provided permalink with form state when JS disabled", + "app-dir action useActionState should support hydrating the app from progressively enhanced form request", + "app-dir action useActionState should support submitting form state with JS", + "app-dir action useActionState should support submitting form state without JS" ], "failed": [], "pending": [], @@ -2764,7 +2774,7 @@ "app dir - external dependency react in external esm packages should use the same react in pages", "app dir - external dependency react in external esm packages should use the same react in server app", "app dir - external dependency server actions should compile server actions from node_modules in client components", - "app dir - external dependency server actions should not prefer to resolve esm over cjs for bundling optout packages", + "app dir - external dependency server actions should prefer to resolve esm over cjs for bundling optout packages", "app dir - external dependency should be able to opt-out 3rd party packages being bundled in server components", "app dir - external dependency should correctly collect global css imports and mark them as side effects", "app dir - external dependency should emit cjs helpers for external cjs modules when compiled", @@ -4079,13 +4089,13 @@ "app dir - metadata dynamic routes social image routes should handle manifest.[ext] dynamic routes", "app dir - metadata dynamic routes social image routes should render og image with opengraph-image dynamic routes", "app dir - metadata dynamic routes social image routes should render og image with twitter-image dynamic routes", - "app dir - metadata dynamic routes social image routes should support generate multi images with generateImageMetadata", - "app dir - metadata dynamic routes social image routes should support generate multi sitemaps with generateSitemaps", "app dir - metadata dynamic routes social image routes should support params as argument in dynamic routes", - "app dir - metadata dynamic routes text routes should handle robots.[ext] dynamic routes", - "app dir - metadata dynamic routes text routes should handle sitemap.[ext] dynamic routes", - "app dir - metadata dynamic routes text routes should not throw if client components are imported but not used", - "app dir - metadata dynamic routes text routes should support alternate.languages in sitemap" + "app dir - metadata dynamic routes social image routes should support generate multi images with generateImageMetadata", + "app dir - metadata dynamic routes sitemap should not throw if client components are imported but not used in sitemap", + "app dir - metadata dynamic routes sitemap should handle sitemap.[ext] dynamic routes", + "app dir - metadata dynamic routes sitemap social image routes should support generate multi sitemaps with generateSitemaps", + "app dir - metadata dynamic routes sitemap should support alternate.languages in sitemap", + "app dir - metadata dynamic routes robots.txt should handle robots.[ext] dynamic routes" ], "failed": [], "pending": [], @@ -4280,15 +4290,15 @@ }, "test/e2e/app-dir/next-font/next-font.test.ts": { "passed": [ - "app dir - next/font app app dir - next-font computed styles should have correct styles at /", - "app dir - next/font app app dir - next-font computed styles should have correct styles at /client", - "app dir - next/font app app dir - next-font import values should have correct values at /", - "app dir - next/font app app dir - next-font import values should have correct values at /client", - "app dir - next/font app app dir - next-font import values should transform code in node_modules", - "app dir - next/font app app dir - next-font navigation should not have duplicate preload tags on navigation" + "app dir - next/font app dir - next-font computed styles should have correct styles at /", + "app dir - next/font app dir - next-font computed styles should have correct styles at /client", + "app dir - next/font app dir - next-font import values should have correct values at /", + "app dir - next/font app dir - next-font import values should have correct values at /client", + "app dir - next/font app dir - next-font import values should transform code in node_modules", + "app dir - next/font app dir - next-font navigation should not have duplicate preload tags on navigation" ], "failed": [ - "app dir - next/font app app dir - next-font Dev errors should recover on font loader error" + "app dir - next/font app dir - next-font Dev errors should recover on font loader error" ], "pending": [], "flakey": [], @@ -4426,7 +4436,6 @@ "test/e2e/app-dir/parallel-route-not-found/parallel-route-not-found.test.ts": { "passed": [ "parallel-route-not-found should handle `notFound()` in a slot", - "parallel-route-not-found should handle `notFound()` in a slot with no `children` slot", "parallel-route-not-found should handle `notFound()` in generateMetadata on a page that also renders a parallel route", "parallel-route-not-found should handle a layout that attempts to render a missing parallel route", "parallel-route-not-found should handle multiple missing parallel routes", @@ -4434,7 +4443,9 @@ "parallel-route-not-found should render the page & slots if all parallel routes are found" ], "failed": [], - "pending": [], + "pending": [ + "parallel-route-not-found should handle `notFound()` in a slot with no `children` slot" + ], "flakey": [], "runtimeError": false }, @@ -4742,6 +4753,13 @@ "flakey": [], "runtimeError": false }, + "test/e2e/app-dir/ppr-incremental/ppr-incremental.test.ts": { + "passed": [], + "failed": [], + "pending": ["ppr-incremental should skip next dev"], + "flakey": [], + "runtimeError": false + }, "test/e2e/app-dir/ppr-navigations/avoid-popstate-flash/avoid-popstate-flash.test.ts": { "passed": ["avoid-popstate-flash ppr is disabled in dev"], "failed": [], @@ -4959,7 +4977,6 @@ "app dir - rsc basics should handle various kinds of exports correctly", "app dir - rsc basics should link correctly with next/link without mpa navigation to the page", "app dir - rsc basics should not apply rsc syntax checks in pages/api", - "app dir - rsc basics should not use bundled react for pages with app", "app dir - rsc basics should render built-in 404 page for missing route if pagesDir is not presented", "app dir - rsc basics should render css-in-js suspense boundary correctly", "app dir - rsc basics should render initial styles of css-in-js in edge SSR correctly", @@ -4980,6 +4997,7 @@ ], "failed": [], "pending": [ + "app dir - rsc basics should not use bundled react for pages with app", "app dir - rsc basics should support partial hydration with inlined server data in browser", "app dir - rsc basics should support webpack loader rules" ], @@ -5368,7 +5386,7 @@ }, "test/e2e/app-dir/server-components-externals/index.test.ts": { "passed": [ - "app-dir - server components externals should have externals for those in config.experimental.serverComponentsExternalPackages", + "app-dir - server components externals should have externals for those in config.serverExternalPackages", "app-dir - server components externals uses externals for predefined list in server-external-packages.json" ], "failed": [], @@ -6969,12 +6987,11 @@ "next test first time setup should correctly install missing dependencies and generate missing configuration file for first-time-setup-js", "next test first time setup should correctly install missing dependencies and generate missing configuration file for first-time-setup-ts", "next test first time setup should fail if next.js config is missing experimental#testProxy", - "next test should execute playwright tests", "next test should pass args to test runner", "next test test runner validation should validate configured/specified test runner" ], "failed": [], - "pending": [], + "pending": ["next test should execute playwright tests"], "flakey": [], "runtimeError": false }, @@ -7707,6 +7724,7 @@ "passed": [ "AMP Usage AMP dev no-warn should not warn on valid amp", "AMP Usage AMP development mode should add data-ampdevmode to development script tags", + "AMP Usage AMP development mode should detect amp validator warning on custom scripts", "AMP Usage AMP development mode should detect amp validator warning on invalid amp", "AMP Usage AMP development mode should navigate from non-AMP to AMP without error", "AMP Usage AMP development mode should not contain missing files warning" @@ -10498,8 +10516,8 @@ "passed": [], "failed": [], "pending": [ - "bundle pages externals with config.experimental.bundlePagesExternals production mode should have no externals with the config set", - "bundle pages externals with config.experimental.bundlePagesExternals production mode should respect the serverComponentsExternals config" + "bundle pages externals with config.bundlePagesRouterDependencies production mode should have no externals with the config set", + "bundle pages externals with config.bundlePagesRouterDependencies production mode should respect the serverExternalPackages config" ], "flakey": [], "runtimeError": false @@ -12756,6 +12774,7 @@ "with contentDispositionType attachment dev support with next.config.js should fail when url has file protocol", "with contentDispositionType attachment dev support with next.config.js should fail when url has ftp protocol", "with contentDispositionType attachment dev support with next.config.js should fail when url is missing", + "with contentDispositionType attachment dev support with next.config.js should fail when url is too long", "with contentDispositionType attachment dev support with next.config.js should fail when w is 0", "with contentDispositionType attachment dev support with next.config.js should fail when w is less than 0", "with contentDispositionType attachment dev support with next.config.js should fail when w is missing", @@ -12768,16 +12787,22 @@ "with contentDispositionType attachment dev support with next.config.js should maintain animated png 2", "with contentDispositionType attachment dev support with next.config.js should maintain animated webp", "with contentDispositionType attachment dev support with next.config.js should maintain bmp", + "with contentDispositionType attachment dev support with next.config.js should maintain icns", "with contentDispositionType attachment dev support with next.config.js should maintain ico format", "with contentDispositionType attachment dev support with next.config.js should maintain jpg format for old Safari", + "with contentDispositionType attachment dev support with next.config.js should maintain pic/pct", "with contentDispositionType attachment dev support with next.config.js should maintain png format for old Safari", "with contentDispositionType attachment dev support with next.config.js should normalize invalid status codes", "with contentDispositionType attachment dev support with next.config.js should not allow svg with application header", "with contentDispositionType attachment dev support with next.config.js should not allow svg with comma header", "with contentDispositionType attachment dev support with next.config.js should not allow svg with uppercase header", + "with contentDispositionType attachment dev support with next.config.js should not allow svg with wrong header", "with contentDispositionType attachment dev support with next.config.js should not allow vector svg", "with contentDispositionType attachment dev support with next.config.js should not resize if requested width is larger than original source image", "with contentDispositionType attachment dev support with next.config.js should resize absolute url from localhost", + "with contentDispositionType attachment dev support with next.config.js should resize avif", + "with contentDispositionType attachment dev support with next.config.js should resize avif and maintain format", + "with contentDispositionType attachment dev support with next.config.js should resize gif (not animated)", "with contentDispositionType attachment dev support with next.config.js should resize relative url and new Chrome accept header as avif", "with contentDispositionType attachment dev support with next.config.js should resize relative url and old Chrome accept header as webp", "with contentDispositionType attachment dev support with next.config.js should resize relative url and png accept header", @@ -12785,6 +12810,7 @@ "with contentDispositionType attachment dev support with next.config.js should resize relative url with invalid accept header as gif", "with contentDispositionType attachment dev support with next.config.js should resize relative url with invalid accept header as png", "with contentDispositionType attachment dev support with next.config.js should resize relative url with invalid accept header as tiff", + "with contentDispositionType attachment dev support with next.config.js should resize tiff", "with contentDispositionType attachment dev support with next.config.js should return home page", "with contentDispositionType attachment dev support with next.config.js should set 304 status without body when etag matches if-none-match", "with contentDispositionType attachment dev support with next.config.js should set cache-control to immutable for static images", @@ -12814,6 +12840,7 @@ "with contentDispositionType attachment Production Mode Server support with next.config.js should fail when url has file protocol", "with contentDispositionType attachment Production Mode Server support with next.config.js should fail when url has ftp protocol", "with contentDispositionType attachment Production Mode Server support with next.config.js should fail when url is missing", + "with contentDispositionType attachment Production Mode Server support with next.config.js should fail when url is too long", "with contentDispositionType attachment Production Mode Server support with next.config.js should fail when w is 0", "with contentDispositionType attachment Production Mode Server support with next.config.js should fail when w is less than 0", "with contentDispositionType attachment Production Mode Server support with next.config.js should fail when w is missing", @@ -12826,16 +12853,22 @@ "with contentDispositionType attachment Production Mode Server support with next.config.js should maintain animated png 2", "with contentDispositionType attachment Production Mode Server support with next.config.js should maintain animated webp", "with contentDispositionType attachment Production Mode Server support with next.config.js should maintain bmp", + "with contentDispositionType attachment Production Mode Server support with next.config.js should maintain icns", "with contentDispositionType attachment Production Mode Server support with next.config.js should maintain ico format", "with contentDispositionType attachment Production Mode Server support with next.config.js should maintain jpg format for old Safari", + "with contentDispositionType attachment Production Mode Server support with next.config.js should maintain pic/pct", "with contentDispositionType attachment Production Mode Server support with next.config.js should maintain png format for old Safari", "with contentDispositionType attachment Production Mode Server support with next.config.js should normalize invalid status codes", "with contentDispositionType attachment Production Mode Server support with next.config.js should not allow svg with application header", "with contentDispositionType attachment Production Mode Server support with next.config.js should not allow svg with comma header", "with contentDispositionType attachment Production Mode Server support with next.config.js should not allow svg with uppercase header", + "with contentDispositionType attachment Production Mode Server support with next.config.js should not allow svg with wrong header", "with contentDispositionType attachment Production Mode Server support with next.config.js should not allow vector svg", "with contentDispositionType attachment Production Mode Server support with next.config.js should not resize if requested width is larger than original source image", "with contentDispositionType attachment Production Mode Server support with next.config.js should resize absolute url from localhost", + "with contentDispositionType attachment Production Mode Server support with next.config.js should resize avif", + "with contentDispositionType attachment Production Mode Server support with next.config.js should resize avif and maintain format", + "with contentDispositionType attachment Production Mode Server support with next.config.js should resize gif (not animated)", "with contentDispositionType attachment Production Mode Server support with next.config.js should resize relative url and new Chrome accept header as avif", "with contentDispositionType attachment Production Mode Server support with next.config.js should resize relative url and old Chrome accept header as webp", "with contentDispositionType attachment Production Mode Server support with next.config.js should resize relative url and png accept header", @@ -12843,6 +12876,7 @@ "with contentDispositionType attachment Production Mode Server support with next.config.js should resize relative url with invalid accept header as gif", "with contentDispositionType attachment Production Mode Server support with next.config.js should resize relative url with invalid accept header as png", "with contentDispositionType attachment Production Mode Server support with next.config.js should resize relative url with invalid accept header as tiff", + "with contentDispositionType attachment Production Mode Server support with next.config.js should resize tiff", "with contentDispositionType attachment Production Mode Server support with next.config.js should return home page", "with contentDispositionType attachment Production Mode Server support with next.config.js should set 304 status without body when etag matches if-none-match", "with contentDispositionType attachment Production Mode Server support with next.config.js should set cache-control to immutable for static images", @@ -12853,6 +12887,135 @@ "flakey": [], "runtimeError": false }, + "test/integration/image-optimizer/test/dangerously-allow-svg.test.ts": { + "passed": [ + "with dangerouslyAllowSVG config dev support with next.config.js should automatically detect image type when content-type is octet-stream", + "with dangerouslyAllowSVG config dev support with next.config.js should compress avif smaller than webp at q=100", + "with dangerouslyAllowSVG config dev support with next.config.js should compress avif smaller than webp at q=50", + "with dangerouslyAllowSVG config dev support with next.config.js should compress avif smaller than webp at q=75", + "with dangerouslyAllowSVG config dev support with next.config.js should downlevel avif format to jpeg for old Safari", + "with dangerouslyAllowSVG config dev support with next.config.js should downlevel webp format to jpeg for old Safari", + "with dangerouslyAllowSVG config dev support with next.config.js should emit blur svg when width is 8 in dev but not prod", + "with dangerouslyAllowSVG config dev support with next.config.js should emit blur svg when width is less than 8 in dev but not prod", + "with dangerouslyAllowSVG config dev support with next.config.js should error if the image file does not exist", + "with dangerouslyAllowSVG config dev support with next.config.js should error if the resource isn't a valid image", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when domain is not defined in next.config.js", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when internal url is not an image", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when q is greater than 100", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when q is less than 1", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when q is missing", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when q is not a number", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when url fails to load an image", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when url has file protocol", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when url has ftp protocol", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when url is missing", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when url is too long", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when w is 0", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when w is less than 0", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when w is missing", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when w is not a number", + "with dangerouslyAllowSVG config dev support with next.config.js should fail when width is not in next.config.js", + "with dangerouslyAllowSVG config dev support with next.config.js should handle concurrent requests", + "with dangerouslyAllowSVG config dev support with next.config.js should handle non-ascii characters in image url", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain animated gif", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain animated png", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain animated png 2", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain animated webp", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain bmp", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain icns", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain ico format", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain jpg format for old Safari", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain pic/pct", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain png format for old Safari", + "with dangerouslyAllowSVG config dev support with next.config.js should maintain vector svg", + "with dangerouslyAllowSVG config dev support with next.config.js should normalize invalid status codes", + "with dangerouslyAllowSVG config dev support with next.config.js should not resize if requested width is larger than original source image", + "with dangerouslyAllowSVG config dev support with next.config.js should resize absolute url from localhost", + "with dangerouslyAllowSVG config dev support with next.config.js should resize avif", + "with dangerouslyAllowSVG config dev support with next.config.js should resize avif and maintain format", + "with dangerouslyAllowSVG config dev support with next.config.js should resize gif (not animated)", + "with dangerouslyAllowSVG config dev support with next.config.js should resize relative url and new Chrome accept header as avif", + "with dangerouslyAllowSVG config dev support with next.config.js should resize relative url and old Chrome accept header as webp", + "with dangerouslyAllowSVG config dev support with next.config.js should resize relative url and png accept header", + "with dangerouslyAllowSVG config dev support with next.config.js should resize relative url and webp Firefox accept header", + "with dangerouslyAllowSVG config dev support with next.config.js should resize relative url with invalid accept header as gif", + "with dangerouslyAllowSVG config dev support with next.config.js should resize relative url with invalid accept header as png", + "with dangerouslyAllowSVG config dev support with next.config.js should resize relative url with invalid accept header as tiff", + "with dangerouslyAllowSVG config dev support with next.config.js should resize tiff", + "with dangerouslyAllowSVG config dev support with next.config.js should return home page", + "with dangerouslyAllowSVG config dev support with next.config.js should set 304 status without body when etag matches if-none-match", + "with dangerouslyAllowSVG config dev support with next.config.js should set cache-control to immutable for static images", + "with dangerouslyAllowSVG config dev support with next.config.js should use cache and stale-while-revalidate when query is the same for external image", + "with dangerouslyAllowSVG config dev support with next.config.js should use cache and stale-while-revalidate when query is the same for internal image", + "with dangerouslyAllowSVG config dev support with next.config.js should use cached image file when parameters are the same for animated gif", + "with dangerouslyAllowSVG config dev support with next.config.js should use cached image file when parameters are the same for svg" + ], + "failed": [], + "pending": [ + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should automatically detect image type when content-type is octet-stream", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should compress avif smaller than webp at q=100", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should compress avif smaller than webp at q=50", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should compress avif smaller than webp at q=75", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should downlevel avif format to jpeg for old Safari", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should downlevel webp format to jpeg for old Safari", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should emit blur svg when width is 8 in dev but not prod", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should emit blur svg when width is less than 8 in dev but not prod", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should error if the image file does not exist", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should error if the resource isn't a valid image", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when domain is not defined in next.config.js", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when internal url is not an image", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when q is greater than 100", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when q is less than 1", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when q is missing", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when q is not a number", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when url fails to load an image", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when url has file protocol", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when url has ftp protocol", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when url is missing", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when url is too long", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when w is 0", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when w is less than 0", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when w is missing", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when w is not a number", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should fail when width is not in next.config.js", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should handle concurrent requests", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should handle non-ascii characters in image url", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain animated gif", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain animated png", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain animated png 2", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain animated webp", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain bmp", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain icns", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain ico format", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain jpg format for old Safari", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain pic/pct", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain png format for old Safari", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should maintain vector svg", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should normalize invalid status codes", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should not resize if requested width is larger than original source image", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize absolute url from localhost", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize avif", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize avif and maintain format", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize gif (not animated)", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize relative url and new Chrome accept header as avif", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize relative url and old Chrome accept header as webp", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize relative url and png accept header", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize relative url and webp Firefox accept header", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize relative url with invalid accept header as gif", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize relative url with invalid accept header as png", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize relative url with invalid accept header as tiff", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should resize tiff", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should return home page", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should set 304 status without body when etag matches if-none-match", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should set cache-control to immutable for static images", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should use cache and stale-while-revalidate when query is the same for external image", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should use cache and stale-while-revalidate when query is the same for internal image", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should use cached image file when parameters are the same for animated gif", + "with dangerouslyAllowSVG config Production Mode Server support with next.config.js should use cached image file when parameters are the same for svg" + ], + "flakey": [], + "runtimeError": false + }, "test/integration/image-optimizer/test/index.test.ts": { "passed": [ "Image Optimizer Server support for trailingSlash in next.config.js should return successful response for original loader", @@ -12910,6 +13073,7 @@ "with minimumCacheTTL of 5 sec dev support with next.config.js should fail when url has file protocol", "with minimumCacheTTL of 5 sec dev support with next.config.js should fail when url has ftp protocol", "with minimumCacheTTL of 5 sec dev support with next.config.js should fail when url is missing", + "with minimumCacheTTL of 5 sec dev support with next.config.js should fail when url is too long", "with minimumCacheTTL of 5 sec dev support with next.config.js should fail when w is 0", "with minimumCacheTTL of 5 sec dev support with next.config.js should fail when w is less than 0", "with minimumCacheTTL of 5 sec dev support with next.config.js should fail when w is missing", @@ -12922,16 +13086,22 @@ "with minimumCacheTTL of 5 sec dev support with next.config.js should maintain animated png 2", "with minimumCacheTTL of 5 sec dev support with next.config.js should maintain animated webp", "with minimumCacheTTL of 5 sec dev support with next.config.js should maintain bmp", + "with minimumCacheTTL of 5 sec dev support with next.config.js should maintain icns", "with minimumCacheTTL of 5 sec dev support with next.config.js should maintain ico format", "with minimumCacheTTL of 5 sec dev support with next.config.js should maintain jpg format for old Safari", + "with minimumCacheTTL of 5 sec dev support with next.config.js should maintain pic/pct", "with minimumCacheTTL of 5 sec dev support with next.config.js should maintain png format for old Safari", "with minimumCacheTTL of 5 sec dev support with next.config.js should normalize invalid status codes", "with minimumCacheTTL of 5 sec dev support with next.config.js should not allow svg with application header", "with minimumCacheTTL of 5 sec dev support with next.config.js should not allow svg with comma header", "with minimumCacheTTL of 5 sec dev support with next.config.js should not allow svg with uppercase header", + "with minimumCacheTTL of 5 sec dev support with next.config.js should not allow svg with wrong header", "with minimumCacheTTL of 5 sec dev support with next.config.js should not allow vector svg", "with minimumCacheTTL of 5 sec dev support with next.config.js should not resize if requested width is larger than original source image", "with minimumCacheTTL of 5 sec dev support with next.config.js should resize absolute url from localhost", + "with minimumCacheTTL of 5 sec dev support with next.config.js should resize avif", + "with minimumCacheTTL of 5 sec dev support with next.config.js should resize avif and maintain format", + "with minimumCacheTTL of 5 sec dev support with next.config.js should resize gif (not animated)", "with minimumCacheTTL of 5 sec dev support with next.config.js should resize relative url and new Chrome accept header as avif", "with minimumCacheTTL of 5 sec dev support with next.config.js should resize relative url and old Chrome accept header as webp", "with minimumCacheTTL of 5 sec dev support with next.config.js should resize relative url and png accept header", @@ -12939,6 +13109,7 @@ "with minimumCacheTTL of 5 sec dev support with next.config.js should resize relative url with invalid accept header as gif", "with minimumCacheTTL of 5 sec dev support with next.config.js should resize relative url with invalid accept header as png", "with minimumCacheTTL of 5 sec dev support with next.config.js should resize relative url with invalid accept header as tiff", + "with minimumCacheTTL of 5 sec dev support with next.config.js should resize tiff", "with minimumCacheTTL of 5 sec dev support with next.config.js should return home page", "with minimumCacheTTL of 5 sec dev support with next.config.js should set 304 status without body when etag matches if-none-match", "with minimumCacheTTL of 5 sec dev support with next.config.js should set cache-control to immutable for static images", @@ -12968,6 +13139,7 @@ "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should fail when url has file protocol", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should fail when url has ftp protocol", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should fail when url is missing", + "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should fail when url is too long", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should fail when w is 0", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should fail when w is less than 0", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should fail when w is missing", @@ -12980,16 +13152,22 @@ "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should maintain animated png 2", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should maintain animated webp", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should maintain bmp", + "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should maintain icns", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should maintain ico format", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should maintain jpg format for old Safari", + "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should maintain pic/pct", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should maintain png format for old Safari", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should normalize invalid status codes", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should not allow svg with application header", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should not allow svg with comma header", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should not allow svg with uppercase header", + "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should not allow svg with wrong header", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should not allow vector svg", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should not resize if requested width is larger than original source image", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should resize absolute url from localhost", + "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should resize avif", + "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should resize avif and maintain format", + "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should resize gif (not animated)", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should resize relative url and new Chrome accept header as avif", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should resize relative url and old Chrome accept header as webp", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should resize relative url and png accept header", @@ -12997,6 +13175,7 @@ "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should resize relative url with invalid accept header as gif", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should resize relative url with invalid accept header as png", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should resize relative url with invalid accept header as tiff", + "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should resize tiff", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should return home page", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should set 304 status without body when etag matches if-none-match", "with minimumCacheTTL of 5 sec Production Mode Server support with next.config.js should set cache-control to immutable for static images", @@ -13024,6 +13203,7 @@ "with latest sharp dev support w/o next.config.js should fail when url has file protocol", "with latest sharp dev support w/o next.config.js should fail when url has ftp protocol", "with latest sharp dev support w/o next.config.js should fail when url is missing", + "with latest sharp dev support w/o next.config.js should fail when url is too long", "with latest sharp dev support w/o next.config.js should fail when w is 0", "with latest sharp dev support w/o next.config.js should fail when w is less than 0", "with latest sharp dev support w/o next.config.js should fail when w is missing", @@ -13035,20 +13215,26 @@ "with latest sharp dev support w/o next.config.js should maintain animated png 2", "with latest sharp dev support w/o next.config.js should maintain animated webp", "with latest sharp dev support w/o next.config.js should maintain bmp", + "with latest sharp dev support w/o next.config.js should maintain icns", "with latest sharp dev support w/o next.config.js should maintain ico format", "with latest sharp dev support w/o next.config.js should maintain jpg format for old Safari", + "with latest sharp dev support w/o next.config.js should maintain pic/pct", "with latest sharp dev support w/o next.config.js should maintain png format for old Safari", "with latest sharp dev support w/o next.config.js should not allow svg with application header", "with latest sharp dev support w/o next.config.js should not allow svg with comma header", "with latest sharp dev support w/o next.config.js should not allow svg with uppercase header", + "with latest sharp dev support w/o next.config.js should not allow svg with wrong header", "with latest sharp dev support w/o next.config.js should not allow vector svg", "with latest sharp dev support w/o next.config.js should not resize if requested width is larger than original source image", + "with latest sharp dev support w/o next.config.js should resize avif", + "with latest sharp dev support w/o next.config.js should resize gif (not animated)", "with latest sharp dev support w/o next.config.js should resize relative url and old Chrome accept header as webp", "with latest sharp dev support w/o next.config.js should resize relative url and png accept header", "with latest sharp dev support w/o next.config.js should resize relative url and webp Firefox accept header", "with latest sharp dev support w/o next.config.js should resize relative url with invalid accept header as gif", "with latest sharp dev support w/o next.config.js should resize relative url with invalid accept header as png", "with latest sharp dev support w/o next.config.js should resize relative url with invalid accept header as tiff", + "with latest sharp dev support w/o next.config.js should resize tiff", "with latest sharp dev support w/o next.config.js should return home page", "with latest sharp dev support w/o next.config.js should set 304 status without body when etag matches if-none-match", "with latest sharp dev support w/o next.config.js should set cache-control to immutable for static images", @@ -13074,6 +13260,7 @@ "with latest sharp dev support with next.config.js should fail when url has file protocol", "with latest sharp dev support with next.config.js should fail when url has ftp protocol", "with latest sharp dev support with next.config.js should fail when url is missing", + "with latest sharp dev support with next.config.js should fail when url is too long", "with latest sharp dev support with next.config.js should fail when w is 0", "with latest sharp dev support with next.config.js should fail when w is less than 0", "with latest sharp dev support with next.config.js should fail when w is missing", @@ -13086,16 +13273,22 @@ "with latest sharp dev support with next.config.js should maintain animated png 2", "with latest sharp dev support with next.config.js should maintain animated webp", "with latest sharp dev support with next.config.js should maintain bmp", + "with latest sharp dev support with next.config.js should maintain icns", "with latest sharp dev support with next.config.js should maintain ico format", "with latest sharp dev support with next.config.js should maintain jpg format for old Safari", + "with latest sharp dev support with next.config.js should maintain pic/pct", "with latest sharp dev support with next.config.js should maintain png format for old Safari", "with latest sharp dev support with next.config.js should normalize invalid status codes", "with latest sharp dev support with next.config.js should not allow svg with application header", "with latest sharp dev support with next.config.js should not allow svg with comma header", "with latest sharp dev support with next.config.js should not allow svg with uppercase header", + "with latest sharp dev support with next.config.js should not allow svg with wrong header", "with latest sharp dev support with next.config.js should not allow vector svg", "with latest sharp dev support with next.config.js should not resize if requested width is larger than original source image", "with latest sharp dev support with next.config.js should resize absolute url from localhost", + "with latest sharp dev support with next.config.js should resize avif", + "with latest sharp dev support with next.config.js should resize avif and maintain format", + "with latest sharp dev support with next.config.js should resize gif (not animated)", "with latest sharp dev support with next.config.js should resize relative url and new Chrome accept header as avif", "with latest sharp dev support with next.config.js should resize relative url and old Chrome accept header as webp", "with latest sharp dev support with next.config.js should resize relative url and png accept header", @@ -13103,6 +13296,7 @@ "with latest sharp dev support with next.config.js should resize relative url with invalid accept header as gif", "with latest sharp dev support with next.config.js should resize relative url with invalid accept header as png", "with latest sharp dev support with next.config.js should resize relative url with invalid accept header as tiff", + "with latest sharp dev support with next.config.js should resize tiff", "with latest sharp dev support with next.config.js should return home page", "with latest sharp dev support with next.config.js should set 304 status without body when etag matches if-none-match", "with latest sharp dev support with next.config.js should set cache-control to immutable for static images", @@ -13127,6 +13321,7 @@ "with latest sharp Production Mode Server support w/o next.config.js should fail when url has file protocol", "with latest sharp Production Mode Server support w/o next.config.js should fail when url has ftp protocol", "with latest sharp Production Mode Server support w/o next.config.js should fail when url is missing", + "with latest sharp Production Mode Server support w/o next.config.js should fail when url is too long", "with latest sharp Production Mode Server support w/o next.config.js should fail when w is 0", "with latest sharp Production Mode Server support w/o next.config.js should fail when w is less than 0", "with latest sharp Production Mode Server support w/o next.config.js should fail when w is missing", @@ -13138,20 +13333,26 @@ "with latest sharp Production Mode Server support w/o next.config.js should maintain animated png 2", "with latest sharp Production Mode Server support w/o next.config.js should maintain animated webp", "with latest sharp Production Mode Server support w/o next.config.js should maintain bmp", + "with latest sharp Production Mode Server support w/o next.config.js should maintain icns", "with latest sharp Production Mode Server support w/o next.config.js should maintain ico format", "with latest sharp Production Mode Server support w/o next.config.js should maintain jpg format for old Safari", + "with latest sharp Production Mode Server support w/o next.config.js should maintain pic/pct", "with latest sharp Production Mode Server support w/o next.config.js should maintain png format for old Safari", "with latest sharp Production Mode Server support w/o next.config.js should not allow svg with application header", "with latest sharp Production Mode Server support w/o next.config.js should not allow svg with comma header", "with latest sharp Production Mode Server support w/o next.config.js should not allow svg with uppercase header", + "with latest sharp Production Mode Server support w/o next.config.js should not allow svg with wrong header", "with latest sharp Production Mode Server support w/o next.config.js should not allow vector svg", "with latest sharp Production Mode Server support w/o next.config.js should not resize if requested width is larger than original source image", + "with latest sharp Production Mode Server support w/o next.config.js should resize avif", + "with latest sharp Production Mode Server support w/o next.config.js should resize gif (not animated)", "with latest sharp Production Mode Server support w/o next.config.js should resize relative url and old Chrome accept header as webp", "with latest sharp Production Mode Server support w/o next.config.js should resize relative url and png accept header", "with latest sharp Production Mode Server support w/o next.config.js should resize relative url and webp Firefox accept header", "with latest sharp Production Mode Server support w/o next.config.js should resize relative url with invalid accept header as gif", "with latest sharp Production Mode Server support w/o next.config.js should resize relative url with invalid accept header as png", "with latest sharp Production Mode Server support w/o next.config.js should resize relative url with invalid accept header as tiff", + "with latest sharp Production Mode Server support w/o next.config.js should resize tiff", "with latest sharp Production Mode Server support w/o next.config.js should return home page", "with latest sharp Production Mode Server support w/o next.config.js should set 304 status without body when etag matches if-none-match", "with latest sharp Production Mode Server support w/o next.config.js should set cache-control to immutable for static images", @@ -13177,6 +13378,7 @@ "with latest sharp Production Mode Server support with next.config.js should fail when url has file protocol", "with latest sharp Production Mode Server support with next.config.js should fail when url has ftp protocol", "with latest sharp Production Mode Server support with next.config.js should fail when url is missing", + "with latest sharp Production Mode Server support with next.config.js should fail when url is too long", "with latest sharp Production Mode Server support with next.config.js should fail when w is 0", "with latest sharp Production Mode Server support with next.config.js should fail when w is less than 0", "with latest sharp Production Mode Server support with next.config.js should fail when w is missing", @@ -13189,16 +13391,22 @@ "with latest sharp Production Mode Server support with next.config.js should maintain animated png 2", "with latest sharp Production Mode Server support with next.config.js should maintain animated webp", "with latest sharp Production Mode Server support with next.config.js should maintain bmp", + "with latest sharp Production Mode Server support with next.config.js should maintain icns", "with latest sharp Production Mode Server support with next.config.js should maintain ico format", "with latest sharp Production Mode Server support with next.config.js should maintain jpg format for old Safari", + "with latest sharp Production Mode Server support with next.config.js should maintain pic/pct", "with latest sharp Production Mode Server support with next.config.js should maintain png format for old Safari", "with latest sharp Production Mode Server support with next.config.js should normalize invalid status codes", "with latest sharp Production Mode Server support with next.config.js should not allow svg with application header", "with latest sharp Production Mode Server support with next.config.js should not allow svg with comma header", "with latest sharp Production Mode Server support with next.config.js should not allow svg with uppercase header", + "with latest sharp Production Mode Server support with next.config.js should not allow svg with wrong header", "with latest sharp Production Mode Server support with next.config.js should not allow vector svg", "with latest sharp Production Mode Server support with next.config.js should not resize if requested width is larger than original source image", "with latest sharp Production Mode Server support with next.config.js should resize absolute url from localhost", + "with latest sharp Production Mode Server support with next.config.js should resize avif", + "with latest sharp Production Mode Server support with next.config.js should resize avif and maintain format", + "with latest sharp Production Mode Server support with next.config.js should resize gif (not animated)", "with latest sharp Production Mode Server support with next.config.js should resize relative url and new Chrome accept header as avif", "with latest sharp Production Mode Server support with next.config.js should resize relative url and old Chrome accept header as webp", "with latest sharp Production Mode Server support with next.config.js should resize relative url and png accept header", @@ -13206,6 +13414,7 @@ "with latest sharp Production Mode Server support with next.config.js should resize relative url with invalid accept header as gif", "with latest sharp Production Mode Server support with next.config.js should resize relative url with invalid accept header as png", "with latest sharp Production Mode Server support with next.config.js should resize relative url with invalid accept header as tiff", + "with latest sharp Production Mode Server support with next.config.js should resize tiff", "with latest sharp Production Mode Server support with next.config.js should return home page", "with latest sharp Production Mode Server support with next.config.js should set 304 status without body when etag matches if-none-match", "with latest sharp Production Mode Server support with next.config.js should set cache-control to immutable for static images", @@ -15027,13 +15236,13 @@ "flakey": [], "runtimeError": false }, - "test/integration/react-18/test/index.test.js": { + "test/integration/react-current-version/test/index.test.js": { "passed": [ - "Basics default setting with react 18 dev hydrates correctly for normal page", - "Basics default setting with react 18 dev no warnings for image related link props", - "Basics default setting with react 18 dev should contain dynamicIds in next data for dynamic imports", - "Basics default setting with react 18 dev should only render once in SSR", - "Basics default setting with react 18 dev useId() values should match on hydration", + "Basics default setting dev hydrates correctly for normal page", + "Basics default setting dev no warnings for image related link props", + "Basics default setting dev should contain dynamicIds in next data for dynamic imports", + "Basics default setting dev should only render once in SSR", + "Basics default setting dev useId() values should match on hydration", "Concurrent mode in the experimental-edge runtime dev should not have the initial route announced", "Concurrent mode in the experimental-edge runtime dev flushes styled-jsx styles as the page renders", "Concurrent mode in the experimental-edge runtime dev should not have invalid config warning", @@ -15043,11 +15252,11 @@ ], "failed": [], "pending": [ - "Basics production mode default setting with react 18 prod hydrates correctly for normal page", - "Basics production mode default setting with react 18 prod no warnings for image related link props", - "Basics production mode default setting with react 18 prod should contain dynamicIds in next data for dynamic imports", - "Basics production mode default setting with react 18 prod should only render once in SSR", - "Basics production mode default setting with react 18 prod useId() values should match on hydration", + "Basics production mode default setting prod hydrates correctly for normal page", + "Basics production mode default setting prod no warnings for image related link props", + "Basics production mode default setting prod should contain dynamicIds in next data for dynamic imports", + "Basics production mode default setting prod should only render once in SSR", + "Basics production mode default setting prod useId() values should match on hydration", "production mode Concurrent mode in the experimental-edge runtime prod should not have the initial route announced", "production mode Concurrent mode in the experimental-edge runtime prod flushes styled-jsx styles as the page renders", "production mode Concurrent mode in the experimental-edge runtime prod should not have invalid config warning", diff --git a/test/unit/image-optimizer/detect-content-type.test.ts b/test/unit/image-optimizer/detect-content-type.test.ts index 24df3cd9a48d3..d8731cca0096a 100644 --- a/test/unit/image-optimizer/detect-content-type.test.ts +++ b/test/unit/image-optimizer/detect-content-type.test.ts @@ -22,6 +22,10 @@ describe('detectContentType', () => { const buffer = await getImage('./images/test.svg') expect(detectContentType(buffer)).toBe('image/svg+xml') }) + it('should return svg for inline svg', async () => { + const buffer = await getImage('./images/test-inline.svg') + expect(detectContentType(buffer)).toBe('image/svg+xml') + }) it('should return avif', async () => { const buffer = await getImage('./images/test.avif') expect(detectContentType(buffer)).toBe('image/avif') diff --git a/test/unit/image-optimizer/images/test-inline.svg b/test/unit/image-optimizer/images/test-inline.svg new file mode 100644 index 0000000000000..811eeaf6b154e --- /dev/null +++ b/test/unit/image-optimizer/images/test-inline.svg @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/test/unit/incremental-cache/file-system-cache.test.ts b/test/unit/incremental-cache/file-system-cache.test.ts index 7e22c3eac76f2..34267dc6a15e7 100644 --- a/test/unit/incremental-cache/file-system-cache.test.ts +++ b/test/unit/incremental-cache/file-system-cache.test.ts @@ -15,9 +15,7 @@ describe('FileSystemCache', () => { fs: nodeFs, serverDistDir: cacheDir, revalidatedTags: [], - experimental: { - ppr: false, - }, + isAppPPREnabled: false, }) const binary = await fs.readFile( @@ -37,7 +35,7 @@ describe('FileSystemCache', () => { {} ) - expect((await fsCache.get('icon.png')).value).toEqual({ + expect((await fsCache.get('icon.png'))?.value).toEqual({ body: binary, headers: { 'Content-Type': 'image/png', @@ -57,9 +55,7 @@ describe('FileSystemCache (isrMemory 0)', () => { fs: nodeFs, serverDistDir: cacheDir, revalidatedTags: [], - experimental: { - ppr: false, - }, + isAppPPREnabled: false, maxMemoryCacheSize: 0, // disable memory cache }) @@ -90,7 +86,7 @@ describe('FileSystemCache (isrMemory 0)', () => { kindHint: 'fetch', }) - expect(res.value).toEqual({ + expect(res?.value).toEqual({ kind: 'FETCH', data: { headers: {}, @@ -119,7 +115,7 @@ describe('FileSystemCache (isrMemory 0)', () => { kindHint: 'fetch', }) - expect(res.value).toEqual({ + expect(res?.value).toEqual({ kind: 'FETCH', data: { headers: {}, body: '1700056381', status: 200, url: '' }, revalidate: 30,