diff --git a/test/e2e/app-dir/revalidatetag-rsc/revalidatetag-rsc.test.ts b/test/e2e/app-dir/revalidatetag-rsc/revalidatetag-rsc.test.ts
index d321f40b65cf6..0b305f6b84b98 100644
--- a/test/e2e/app-dir/revalidatetag-rsc/revalidatetag-rsc.test.ts
+++ b/test/e2e/app-dir/revalidatetag-rsc/revalidatetag-rsc.test.ts
@@ -1,12 +1,12 @@
import { nextTestSetup } from 'e2e-utils'
import { assertHasRedbox, getRedboxHeader, retry } from 'next-test-utils'
-describe('unstable_expireTag-rsc', () => {
+describe('revalidateTag-rsc', () => {
const { next, isNextDev, isNextDeploy } = nextTestSetup({
files: __dirname,
})
- it('should revalidate fetch cache if unstable_expireTag invoked via server action', async () => {
+ it('should revalidate fetch cache if revalidateTag invoked via server action', async () => {
const browser = await next.browser('/')
const randomNumber = await browser.elementById('data').text()
await browser.refresh()
@@ -23,14 +23,14 @@ describe('unstable_expireTag-rsc', () => {
if (!isNextDeploy) {
// skipped in deploy because it uses `next.cliOutput`
- it('should error if unstable_expireTag is called during render', async () => {
+ it('should error if revalidateTag is called during render', async () => {
const browser = await next.browser('/')
await browser.elementByCss('#revalidate-via-page').click()
if (isNextDev) {
await assertHasRedbox(browser)
await expect(getRedboxHeader(browser)).resolves.toContain(
- 'Route /revalidate_via_page used "unstable_expireTag data"'
+ 'Route /revalidate_via_page used "revalidateTag data"'
)
} else {
await retry(async () => {
@@ -41,7 +41,7 @@ describe('unstable_expireTag-rsc', () => {
}
expect(next.cliOutput).toContain(
- 'Route /revalidate_via_page used "unstable_expireTag data"'
+ 'Route /revalidate_via_page used "revalidateTag data"'
)
})
}
diff --git a/test/e2e/app-dir/root-layout/app/(mpa-navigation)/with-parallel-routes/@one/default.js b/test/e2e/app-dir/root-layout/app/(mpa-navigation)/with-parallel-routes/@one/default.js
new file mode 100644
index 0000000000000..6dbe479afc29b
--- /dev/null
+++ b/test/e2e/app-dir/root-layout/app/(mpa-navigation)/with-parallel-routes/@one/default.js
@@ -0,0 +1,5 @@
+import { notFound } from 'next/navigation'
+
+export default function Default() {
+ notFound()
+}
diff --git a/test/e2e/app-dir/root-layout/app/(mpa-navigation)/with-parallel-routes/@two/default.js b/test/e2e/app-dir/root-layout/app/(mpa-navigation)/with-parallel-routes/@two/default.js
new file mode 100644
index 0000000000000..6dbe479afc29b
--- /dev/null
+++ b/test/e2e/app-dir/root-layout/app/(mpa-navigation)/with-parallel-routes/@two/default.js
@@ -0,0 +1,5 @@
+import { notFound } from 'next/navigation'
+
+export default function Default() {
+ notFound()
+}
diff --git a/test/e2e/app-dir/rsc-basic/app/(group)/conventions/@named/default.js b/test/e2e/app-dir/rsc-basic/app/(group)/conventions/@named/default.js
new file mode 100644
index 0000000000000..6dbe479afc29b
--- /dev/null
+++ b/test/e2e/app-dir/rsc-basic/app/(group)/conventions/@named/default.js
@@ -0,0 +1,5 @@
+import { notFound } from 'next/navigation'
+
+export default function Default() {
+ notFound()
+}
diff --git a/test/e2e/app-dir/segment-cache/basic/app/test/@nav/default.tsx b/test/e2e/app-dir/segment-cache/basic/app/test/@nav/default.tsx
new file mode 100644
index 0000000000000..6dbe479afc29b
--- /dev/null
+++ b/test/e2e/app-dir/segment-cache/basic/app/test/@nav/default.tsx
@@ -0,0 +1,5 @@
+import { notFound } from 'next/navigation'
+
+export default function Default() {
+ notFound()
+}
diff --git a/test/e2e/app-dir/segment-cache/revalidation/app/page.tsx b/test/e2e/app-dir/segment-cache/revalidation/app/page.tsx
index d4a410c6f1061..5521a212d9a73 100644
--- a/test/e2e/app-dir/segment-cache/revalidation/app/page.tsx
+++ b/test/e2e/app-dir/segment-cache/revalidation/app/page.tsx
@@ -1,4 +1,4 @@
-import { revalidatePath, revalidateTag } from 'next/cache'
+import { revalidatePath, updateTag } from 'next/cache'
import {
LinkAccordion,
FormAccordion,
@@ -23,7 +23,7 @@ export default async function Page() {
id="revalidate-by-tag"
formAction={async function () {
'use server'
- revalidateTag('random-greeting')
+ updateTag('random-greeting')
}}
>
Revalidate by tag
diff --git a/test/e2e/app-dir/typed-routes/app/dashboard/@analytics/default.tsx b/test/e2e/app-dir/typed-routes/app/dashboard/@analytics/default.tsx
new file mode 100644
index 0000000000000..6dbe479afc29b
--- /dev/null
+++ b/test/e2e/app-dir/typed-routes/app/dashboard/@analytics/default.tsx
@@ -0,0 +1,5 @@
+import { notFound } from 'next/navigation'
+
+export default function Default() {
+ notFound()
+}
diff --git a/test/e2e/app-dir/typed-routes/app/dashboard/@team/default.tsx b/test/e2e/app-dir/typed-routes/app/dashboard/@team/default.tsx
new file mode 100644
index 0000000000000..6dbe479afc29b
--- /dev/null
+++ b/test/e2e/app-dir/typed-routes/app/dashboard/@team/default.tsx
@@ -0,0 +1,5 @@
+import { notFound } from 'next/navigation'
+
+export default function Default() {
+ notFound()
+}
diff --git a/test/e2e/app-dir/use-cache-custom-handler/app/legacy/page.tsx b/test/e2e/app-dir/use-cache-custom-handler/app/legacy/page.tsx
deleted file mode 100644
index 67c60b1382de1..0000000000000
--- a/test/e2e/app-dir/use-cache-custom-handler/app/legacy/page.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import { Suspense } from 'react'
-import {
- unstable_cacheLife as cacheLife,
- unstable_cacheTag as cacheTag,
- revalidateTag,
-} from 'next/cache'
-import { redirect } from 'next/navigation'
-import { connection } from 'next/server'
-import React from 'react'
-
-async function getData() {
- 'use cache: legacy'
-
- cacheLife({ revalidate: 3 })
- cacheTag('legacy')
-
- return new Date().toISOString()
-}
-
-async function AsyncComp() {
- let data = await getData()
-
- return
{data}
-}
-
-export default async function Legacy() {
- await connection()
-
- return (
-
- Loading...}>
-
-
-
-
- )
-}
diff --git a/test/e2e/app-dir/use-cache-custom-handler/app/page.tsx b/test/e2e/app-dir/use-cache-custom-handler/app/page.tsx
index ce1c9b713c6d4..5f0c7f860bcea 100644
--- a/test/e2e/app-dir/use-cache-custom-handler/app/page.tsx
+++ b/test/e2e/app-dir/use-cache-custom-handler/app/page.tsx
@@ -3,7 +3,7 @@ import {
unstable_cacheLife as cacheLife,
unstable_cacheTag as cacheTag,
revalidatePath,
- revalidateTag,
+ updateTag,
} from 'next/cache'
import { redirect } from 'next/navigation'
import { connection } from 'next/server'
@@ -38,7 +38,7 @@ export default async function Home() {
formAction={async () => {
'use server'
- revalidateTag('modern')
+ updateTag('modern')
}}
>
Revalidate Tag
@@ -58,7 +58,7 @@ export default async function Home() {
formAction={async () => {
'use server'
- revalidateTag('modern')
+ updateTag('modern')
redirect('/')
}}
>
diff --git a/test/e2e/app-dir/use-cache-custom-handler/handler.js b/test/e2e/app-dir/use-cache-custom-handler/handler.js
index c0198d7387fd0..40100e166386b 100644
--- a/test/e2e/app-dir/use-cache-custom-handler/handler.js
+++ b/test/e2e/app-dir/use-cache-custom-handler/handler.js
@@ -4,7 +4,7 @@ const defaultCacheHandler =
require('next/dist/server/lib/cache-handlers/default.external').default
/**
- * @type {import('next/dist/server/lib/cache-handlers/types').CacheHandlerV2}
+ * @type {import('next/dist/server/lib/cache-handlers/types').CacheHandler}
*/
const cacheHandler = {
async get(cacheKey, softTags) {
@@ -22,16 +22,16 @@ const cacheHandler = {
return defaultCacheHandler.refreshTags()
},
- async getExpiration(...tags) {
+ async getExpiration(tags) {
console.log('ModernCustomCacheHandler::getExpiration', JSON.stringify(tags))
// Expecting soft tags in `get` to be used by the cache handler for checking
// the expiration of a cache entry, instead of letting Next.js handle it.
return Infinity
},
- async expireTags(...tags) {
- console.log('ModernCustomCacheHandler::expireTags', JSON.stringify(tags))
- return defaultCacheHandler.expireTags(...tags)
+ async updateTags(tags) {
+ console.log('ModernCustomCacheHandler::updateTags', JSON.stringify(tags))
+ return defaultCacheHandler.updateTags(tags)
},
}
diff --git a/test/e2e/app-dir/use-cache-custom-handler/legacy-handler.js b/test/e2e/app-dir/use-cache-custom-handler/legacy-handler.js
deleted file mode 100644
index 6fe8f06b4b291..0000000000000
--- a/test/e2e/app-dir/use-cache-custom-handler/legacy-handler.js
+++ /dev/null
@@ -1,37 +0,0 @@
-// @ts-check
-
-const defaultCacheHandler =
- require('next/dist/server/lib/cache-handlers/default.external').default
-
-/**
- * @type {import('next/dist/server/lib/cache-handlers/types').CacheHandler}
- */
-const cacheHandler = {
- async get(cacheKey, softTags) {
- console.log(
- 'LegacyCustomCacheHandler::get',
- cacheKey,
- JSON.stringify(softTags)
- )
- return defaultCacheHandler.get(cacheKey, softTags)
- },
-
- async set(cacheKey, pendingEntry) {
- console.log('LegacyCustomCacheHandler::set', cacheKey)
- return defaultCacheHandler.set(cacheKey, pendingEntry)
- },
-
- async expireTags(...tags) {
- console.log('LegacyCustomCacheHandler::expireTags', JSON.stringify(tags))
- return defaultCacheHandler.expireTags(...tags)
- },
-
- async receiveExpiredTags(...tags) {
- console.log(
- 'LegacyCustomCacheHandler::receiveExpiredTags',
- JSON.stringify(tags)
- )
- },
-}
-
-module.exports = cacheHandler
diff --git a/test/e2e/app-dir/use-cache-custom-handler/next.config.js b/test/e2e/app-dir/use-cache-custom-handler/next.config.js
index 373992347171e..ebc719d50aeb4 100644
--- a/test/e2e/app-dir/use-cache-custom-handler/next.config.js
+++ b/test/e2e/app-dir/use-cache-custom-handler/next.config.js
@@ -6,7 +6,6 @@ const nextConfig = {
cacheComponents: true,
cacheHandlers: {
default: require.resolve('./handler.js'),
- legacy: require.resolve('./legacy-handler.js'),
},
},
}
diff --git a/test/e2e/app-dir/use-cache-custom-handler/use-cache-custom-handler.test.ts b/test/e2e/app-dir/use-cache-custom-handler/use-cache-custom-handler.test.ts
index 72c5469ec9992..98375aaf411ae 100644
--- a/test/e2e/app-dir/use-cache-custom-handler/use-cache-custom-handler.test.ts
+++ b/test/e2e/app-dir/use-cache-custom-handler/use-cache-custom-handler.test.ts
@@ -72,46 +72,6 @@ describe('use-cache-custom-handler', () => {
expect(cliOutput).not.toContain('ModernCustomCacheHandler::refreshTags')
expect(cliOutput).not.toContain(`ModernCustomCacheHandler::getExpiration`)
-
- // We don't optimize for legacy cache handlers though:
- expect(cliOutput).toContain(
- `LegacyCustomCacheHandler::receiveExpiredTags []`
- )
- })
-
- it('should use a legacy custom cache handler if provided', async () => {
- const browser = await next.browser(`/legacy`)
- const initialData = await browser.elementById('data').text()
- expect(initialData).toMatch(isoDateRegExp)
-
- expect(next.cliOutput.slice(outputIndex)).toContain(
- 'LegacyCustomCacheHandler::receiveExpiredTags []'
- )
-
- expect(next.cliOutput.slice(outputIndex)).toMatch(
- /LegacyCustomCacheHandler::get \["(development|[A-Za-z0-9_-]{21})","([0-9a-f]{2})+",\[\]\] \["_N_T_\/layout","_N_T_\/legacy\/layout","_N_T_\/legacy\/page","_N_T_\/legacy"\]/
- )
-
- expect(next.cliOutput.slice(outputIndex)).toMatch(
- /LegacyCustomCacheHandler::set \["(development|[A-Za-z0-9_-]{21})","([0-9a-f]{2})+",\[\]\]/
- )
-
- // The data should be cached initially.
-
- await browser.refresh()
- let data = await browser.elementById('data').text()
- expect(data).toMatch(isoDateRegExp)
- expect(data).toEqual(initialData)
-
- // Because we use a low `revalidate` value for the "use cache" function, new
- // data should be returned eventually.
-
- await retry(async () => {
- await browser.refresh()
- data = await browser.elementById('data').text()
- expect(data).toMatch(isoDateRegExp)
- expect(data).not.toEqual(initialData)
- }, 5000)
})
it('should revalidate after redirect using a modern custom cache handler', async () => {
@@ -123,33 +83,7 @@ describe('use-cache-custom-handler', () => {
await retry(async () => {
expect(next.cliOutput.slice(outputIndex)).toContain(
- 'ModernCustomCacheHandler::expireTags ["modern"]'
- )
-
- const data = await browser.elementById('data').text()
- expect(data).toMatch(isoDateRegExp)
- expect(data).not.toEqual(initialData)
- }, 5000)
- })
-
- it('should revalidate after redirect using a legacy custom cache handler', async () => {
- const browser = await next.browser(`/legacy`)
- const initialData = await browser.elementById('data').text()
- expect(initialData).toMatch(isoDateRegExp)
-
- expect(next.cliOutput.slice(outputIndex)).toContain(
- 'LegacyCustomCacheHandler::receiveExpiredTags []'
- )
-
- await browser.elementById('revalidate').click()
-
- await retry(async () => {
- expect(next.cliOutput.slice(outputIndex)).toContain(
- 'LegacyCustomCacheHandler::expireTags ["legacy"]'
- )
-
- expect(next.cliOutput.slice(outputIndex)).toContain(
- 'LegacyCustomCacheHandler::receiveExpiredTags ["legacy"]'
+ 'ModernCustomCacheHandler::updateTags ["modern"]'
)
const data = await browser.elementById('data').text()
@@ -158,13 +92,13 @@ describe('use-cache-custom-handler', () => {
}, 5000)
})
- it('should not call expireTags for a normal invocation', async () => {
+ it('should not call updateTags for a normal invocation', async () => {
await next.fetch(`/`)
await retry(async () => {
const cliOutput = next.cliOutput.slice(outputIndex)
expect(cliOutput).toInclude('ModernCustomCacheHandler::refreshTags')
- expect(cliOutput).not.toInclude('ModernCustomCacheHandler::expireTags')
+ expect(cliOutput).not.toInclude('ModernCustomCacheHandler::updateTags')
})
})
@@ -179,7 +113,7 @@ describe('use-cache-custom-handler', () => {
const cliOutput = next.cliOutput.slice(outputIndex)
expect(cliOutput).not.toInclude('ModernCustomCacheHandler::getExpiration')
expect(cliOutput).toIncludeRepeated(
- `ModernCustomCacheHandler::expireTags`,
+ `ModernCustomCacheHandler::updateTags`,
1
)
})
diff --git a/test/e2e/app-dir/use-cache/app/(dynamic)/revalidate-and-redirect/redirect/page.tsx b/test/e2e/app-dir/use-cache/app/(dynamic)/revalidate-and-redirect/redirect/page.tsx
index f96828fa42b43..158b4ee6afe29 100644
--- a/test/e2e/app-dir/use-cache/app/(dynamic)/revalidate-and-redirect/redirect/page.tsx
+++ b/test/e2e/app-dir/use-cache/app/(dynamic)/revalidate-and-redirect/redirect/page.tsx
@@ -1,4 +1,4 @@
-import { revalidatePath, revalidateTag } from 'next/cache'
+import { revalidatePath, updateTag } from 'next/cache'
import { redirect } from 'next/navigation'
export default function Page() {
@@ -9,7 +9,7 @@ export default function Page() {
formAction={async () => {
'use server'
- revalidateTag('revalidate-and-redirect')
+ updateTag('revalidate-and-redirect')
redirect('/revalidate-and-redirect')
}}
>
diff --git a/test/e2e/app-dir/use-cache/app/(dynamic)/revalidate-and-use/page.tsx b/test/e2e/app-dir/use-cache/app/(dynamic)/revalidate-and-use/page.tsx
index 77b10c50c1d67..871f463d0d870 100644
--- a/test/e2e/app-dir/use-cache/app/(dynamic)/revalidate-and-use/page.tsx
+++ b/test/e2e/app-dir/use-cache/app/(dynamic)/revalidate-and-use/page.tsx
@@ -1,4 +1,4 @@
-import { revalidatePath, revalidateTag, unstable_cacheTag } from 'next/cache'
+import { revalidatePath, unstable_cacheTag, updateTag } from 'next/cache'
import { Form } from './form'
import { connection } from 'next/server'
@@ -26,7 +26,7 @@ export default async function Page() {
const initialCachedValue = await getCachedValue()
if (type === 'tag') {
- revalidateTag('revalidate-and-use')
+ updateTag('revalidate-and-use')
} else {
revalidatePath('/revalidate-and-use')
}
diff --git a/test/e2e/app-dir/use-cache/app/(partially-static)/api/revalidate-redirect/route.ts b/test/e2e/app-dir/use-cache/app/(partially-static)/api/revalidate-redirect/route.ts
index 3ca4e89352798..984f68a3dd40b 100644
--- a/test/e2e/app-dir/use-cache/app/(partially-static)/api/revalidate-redirect/route.ts
+++ b/test/e2e/app-dir/use-cache/app/(partially-static)/api/revalidate-redirect/route.ts
@@ -2,6 +2,6 @@ import { revalidateTag } from 'next/cache'
import { redirect } from 'next/navigation'
export async function GET() {
- revalidateTag('api')
+ revalidateTag('api', 'expireNow')
redirect('/api')
}
diff --git a/test/e2e/app-dir/use-cache/app/(partially-static)/cache-tag/buttons.tsx b/test/e2e/app-dir/use-cache/app/(partially-static)/cache-tag/buttons.tsx
index 2b9ef977ca84c..4f6ddf7baff20 100644
--- a/test/e2e/app-dir/use-cache/app/(partially-static)/cache-tag/buttons.tsx
+++ b/test/e2e/app-dir/use-cache/app/(partially-static)/cache-tag/buttons.tsx
@@ -1,5 +1,5 @@
import React from 'react'
-import { unstable_expirePath, unstable_expireTag } from 'next/cache'
+import { revalidatePath, updateTag } from 'next/cache'
export function RevalidateButtons() {
return (
@@ -8,7 +8,7 @@ export function RevalidateButtons() {
id="revalidate-a"
formAction={async () => {
'use server'
- unstable_expireTag('a')
+ updateTag('a')
}}
>
revalidate a
@@ -17,7 +17,7 @@ export function RevalidateButtons() {
id="revalidate-b"
formAction={async () => {
'use server'
- unstable_expireTag('b')
+ updateTag('b')
}}
>
revalidate b
@@ -26,7 +26,7 @@ export function RevalidateButtons() {
id="revalidate-c"
formAction={async () => {
'use server'
- unstable_expireTag('c')
+ updateTag('c')
}}
>
revalidate c
@@ -35,7 +35,7 @@ export function RevalidateButtons() {
id="revalidate-f"
formAction={async () => {
'use server'
- unstable_expireTag('f')
+ updateTag('f')
}}
>
revalidate f
@@ -44,7 +44,7 @@ export function RevalidateButtons() {
id="revalidate-r"
formAction={async () => {
'use server'
- unstable_expireTag('r')
+ updateTag('r')
}}
>
revalidate r
@@ -53,7 +53,7 @@ export function RevalidateButtons() {
id="revalidate-path"
formAction={async () => {
'use server'
- unstable_expirePath('/cache-tag')
+ revalidatePath('/cache-tag')
}}
>
revalidate path
diff --git a/test/e2e/app-dir/use-cache/app/(partially-static)/form/page.tsx b/test/e2e/app-dir/use-cache/app/(partially-static)/form/page.tsx
index 32ea86041ec45..504805f15dd08 100644
--- a/test/e2e/app-dir/use-cache/app/(partially-static)/form/page.tsx
+++ b/test/e2e/app-dir/use-cache/app/(partially-static)/form/page.tsx
@@ -1,8 +1,8 @@
-import { unstable_expireTag, unstable_cacheTag as cacheTag } from 'next/cache'
+import { updateTag, unstable_cacheTag as cacheTag } from 'next/cache'
async function refresh() {
'use server'
- unstable_expireTag('home')
+ updateTag('home')
}
export default async function Page() {
diff --git a/test/e2e/app-dir/use-cache/next.config.js b/test/e2e/app-dir/use-cache/next.config.js
index b1c00b3d8cd76..406bcbd170979 100644
--- a/test/e2e/app-dir/use-cache/next.config.js
+++ b/test/e2e/app-dir/use-cache/next.config.js
@@ -10,6 +10,11 @@ const nextConfig = {
revalidate: 100,
expire: 300,
},
+ expireNow: {
+ stale: 0,
+ expire: 0,
+ revalidate: 0,
+ },
},
cacheHandlers: {
custom: require.resolve(
diff --git a/test/e2e/app-dir/use-cache/use-cache.test.ts b/test/e2e/app-dir/use-cache/use-cache.test.ts
index bf456aebceb97..84950005bcb36 100644
--- a/test/e2e/app-dir/use-cache/use-cache.test.ts
+++ b/test/e2e/app-dir/use-cache/use-cache.test.ts
@@ -220,13 +220,13 @@ describe('use-cache', () => {
})
})
- it('should update after unstable_expireTag correctly', async () => {
+ it('should update after revalidateTag correctly', async () => {
const browser = await next.browser('/cache-tag')
const initial = await browser.elementByCss('#a').text()
if (!isNextDev) {
// Bust the ISR cache first, to populate the in-memory cache for the
- // subsequent unstable_expireTag calls.
+ // subsequent revalidateTag calls.
await browser.elementByCss('#revalidate-path').click()
await retry(async () => {
expect(await browser.elementByCss('#a').text()).not.toBe(initial)
@@ -608,7 +608,7 @@ describe('use-cache', () => {
})
})
- it('should be able to revalidate a page using unstable_expireTag', async () => {
+ it('should be able to revalidate a page using revalidateTag', async () => {
const browser = await next.browser(`/form`)
const time1 = await browser.waitForElementByCss('#t').text()
diff --git a/test/e2e/client-max-body-size/app/api/echo/route.ts b/test/e2e/client-max-body-size/app/api/echo/route.ts
index 7752aa7d12c13..ac87608bb83b8 100644
--- a/test/e2e/client-max-body-size/app/api/echo/route.ts
+++ b/test/e2e/client-max-body-size/app/api/echo/route.ts
@@ -1,5 +1,15 @@
import { NextRequest, NextResponse } from 'next/server'
export async function POST(request: NextRequest) {
- return new NextResponse('Hello World', { status: 200 })
+ const body = await request.text()
+ return new NextResponse(
+ JSON.stringify({
+ message: 'Hello World',
+ bodySize: body.length,
+ }),
+ {
+ status: 200,
+ headers: { 'Content-Type': 'application/json' },
+ }
+ )
}
diff --git a/test/e2e/client-max-body-size/index.test.ts b/test/e2e/client-max-body-size/index.test.ts
index dd4326ecf8fb3..ecf28eff21282 100644
--- a/test/e2e/client-max-body-size/index.test.ts
+++ b/test/e2e/client-max-body-size/index.test.ts
@@ -11,7 +11,7 @@ describe('client-max-body-size', () => {
if (skipped) return
- it('should reject request body over 10MB by default', async () => {
+ it('should accept request body over 10MB but only buffer up to limit', async () => {
const bodySize = 11 * 1024 * 1024 // 11MB
const body = 'x'.repeat(bodySize)
@@ -25,8 +25,15 @@ describe('client-max-body-size', () => {
}
)
- expect(res.status).toBe(400)
- expect(next.cliOutput).toContain('Request body exceeded 10MB')
+ expect(res.status).toBe(200)
+ const responseBody = await res.json()
+ expect(responseBody.message).toBe('Hello World')
+ // Should only buffer up to 10MB, not the full 11MB
+ expect(responseBody.bodySize).toBeLessThanOrEqual(10 * 1024 * 1024)
+ expect(responseBody.bodySize).toBeLessThan(bodySize)
+ expect(next.cliOutput).toContain(
+ 'Request body exceeded 10MB for /api/echo'
+ )
})
it('should accept request body at exactly 10MB', async () => {
@@ -44,8 +51,9 @@ describe('client-max-body-size', () => {
)
expect(res.status).toBe(200)
- const responseBody = await res.text()
- expect(responseBody).toBe('Hello World')
+ const responseBody = await res.json()
+ expect(responseBody.message).toBe('Hello World')
+ expect(responseBody.bodySize).toBe(bodySize)
})
it('should accept request body under 10MB', async () => {
@@ -63,8 +71,9 @@ describe('client-max-body-size', () => {
)
expect(res.status).toBe(200)
- const responseBody = await res.text()
- expect(responseBody).toBe('Hello World')
+ const responseBody = await res.json()
+ expect(responseBody.message).toBe('Hello World')
+ expect(responseBody.bodySize).toBe(bodySize)
})
})
@@ -81,7 +90,7 @@ describe('client-max-body-size', () => {
if (skipped) return
- it('should reject request body over custom 5MB limit', async () => {
+ it('should accept request body over custom 5MB limit but only buffer up to limit', async () => {
const bodySize = 6 * 1024 * 1024 // 6MB
const body = 'a'.repeat(bodySize)
@@ -95,8 +104,15 @@ describe('client-max-body-size', () => {
}
)
- expect(res.status).toBe(400)
- expect(next.cliOutput).toContain('Request body exceeded 5MB')
+ expect(res.status).toBe(200)
+ const responseBody = await res.json()
+ expect(responseBody.message).toBe('Hello World')
+ // Should only buffer up to 5MB, not the full 6MB
+ expect(responseBody.bodySize).toBeLessThanOrEqual(5 * 1024 * 1024)
+ expect(responseBody.bodySize).toBeLessThan(bodySize)
+ expect(next.cliOutput).toContain(
+ 'Request body exceeded 5MB for /api/echo'
+ )
})
it('should accept request body under custom 5MB limit', async () => {
@@ -114,8 +130,9 @@ describe('client-max-body-size', () => {
)
expect(res.status).toBe(200)
- const responseBody = await res.text()
- expect(responseBody).toBe('Hello World')
+ const responseBody = await res.json()
+ expect(responseBody.message).toBe('Hello World')
+ expect(responseBody.bodySize).toBe(bodySize)
})
})
@@ -132,7 +149,7 @@ describe('client-max-body-size', () => {
if (skipped) return
- it('should reject request body over custom 2MB limit', async () => {
+ it('should accept request body over custom 2MB limit but only buffer up to limit', async () => {
const bodySize = 3 * 1024 * 1024 // 3MB
const body = 'c'.repeat(bodySize)
@@ -146,8 +163,15 @@ describe('client-max-body-size', () => {
}
)
- expect(res.status).toBe(400)
- expect(next.cliOutput).toContain('Request body exceeded 2MB')
+ expect(res.status).toBe(200)
+ const responseBody = await res.json()
+ expect(responseBody.message).toBe('Hello World')
+ // Should only buffer up to 2MB, not the full 3MB
+ expect(responseBody.bodySize).toBeLessThanOrEqual(2 * 1024 * 1024)
+ expect(responseBody.bodySize).toBeLessThan(bodySize)
+ expect(next.cliOutput).toContain(
+ 'Request body exceeded 2MB for /api/echo'
+ )
})
it('should accept request body under custom 2MB limit', async () => {
@@ -165,8 +189,9 @@ describe('client-max-body-size', () => {
)
expect(res.status).toBe(200)
- const responseBody = await res.text()
- expect(responseBody).toBe('Hello World')
+ const responseBody = await res.json()
+ expect(responseBody.message).toBe('Hello World')
+ expect(responseBody.bodySize).toBe(bodySize)
})
})
@@ -198,11 +223,12 @@ describe('client-max-body-size', () => {
)
expect(res.status).toBe(200)
- const responseBody = await res.text()
- expect(responseBody).toBe('Hello World')
+ const responseBody = await res.json()
+ expect(responseBody.message).toBe('Hello World')
+ expect(responseBody.bodySize).toBe(bodySize)
})
- it('should reject request body over custom 50MB limit', async () => {
+ it('should accept request body over custom 50MB limit but only buffer up to limit', async () => {
const bodySize = 51 * 1024 * 1024 // 51MB
const body = 'f'.repeat(bodySize)
@@ -216,8 +242,15 @@ describe('client-max-body-size', () => {
}
)
- expect(res.status).toBe(400)
- expect(next.cliOutput).toContain('Request body exceeded 50MB')
+ expect(res.status).toBe(200)
+ const responseBody = await res.json()
+ expect(responseBody.message).toBe('Hello World')
+ // Should only buffer up to 50MB, not the full 51MB
+ expect(responseBody.bodySize).toBeLessThanOrEqual(50 * 1024 * 1024)
+ expect(responseBody.bodySize).toBeLessThan(bodySize)
+ expect(next.cliOutput).toContain(
+ 'Request body exceeded 50MB for /api/echo'
+ )
})
})
})
diff --git a/test/e2e/middleware-static-files/app/app/page.tsx b/test/e2e/middleware-static-files/app/app/page.tsx
index dc6405889a044..6517e28e985bf 100644
--- a/test/e2e/middleware-static-files/app/app/page.tsx
+++ b/test/e2e/middleware-static-files/app/app/page.tsx
@@ -22,7 +22,7 @@ export default function Home() {
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
className="font-medium text-zinc-950 dark:text-zinc-50"
>
- Template
+ Templates
{' '}
or the{' '}
{
+ setupTests({
+ nextConfigImages: {
+ dangerouslyAllowLocalIP: true,
+ // Configure external domains so we can try out external redirects
+ domains: [
+ 'localhost',
+ '127.0.0.1',
+ 'example.com',
+ 'assets.vercel.com',
+ 'image-optimization-test.vercel.app',
+ ],
+ // Prevent redirects
+ maximumRedirects: 0,
+ },
+ appDir,
+ })
+})
diff --git a/test/integration/image-optimizer/test/maximum-redirects-1.test.ts b/test/integration/image-optimizer/test/maximum-redirects-1.test.ts
new file mode 100644
index 0000000000000..2a774169d592d
--- /dev/null
+++ b/test/integration/image-optimizer/test/maximum-redirects-1.test.ts
@@ -0,0 +1,23 @@
+import { join } from 'path'
+import { setupTests } from './util'
+
+const appDir = join(__dirname, '../app')
+
+describe('with maximumRedirects 1', () => {
+ setupTests({
+ nextConfigImages: {
+ dangerouslyAllowLocalIP: true,
+ // Configure external domains so we can try out external redirects
+ domains: [
+ 'localhost',
+ '127.0.0.1',
+ 'example.com',
+ 'assets.vercel.com',
+ 'image-optimization-test.vercel.app',
+ ],
+ // Only one redirect
+ maximumRedirects: 1,
+ },
+ appDir,
+ })
+})
diff --git a/test/integration/image-optimizer/test/minimum-cache-ttl.test.ts b/test/integration/image-optimizer/test/minimum-cache-ttl.test.ts
index 73c2c810621e1..ebe1ef4fc7ab5 100644
--- a/test/integration/image-optimizer/test/minimum-cache-ttl.test.ts
+++ b/test/integration/image-optimizer/test/minimum-cache-ttl.test.ts
@@ -6,6 +6,7 @@ const appDir = join(__dirname, '../app')
describe('with minimumCacheTTL of 5 sec', () => {
setupTests({
nextConfigImages: {
+ dangerouslyAllowLocalIP: true,
// Configure external domains so we can try out
// variations of the upstream Cache-Control header.
domains: [
diff --git a/test/integration/image-optimizer/test/util.ts b/test/integration/image-optimizer/test/util.ts
index dbc96e1116e91..3682ea1d04689 100644
--- a/test/integration/image-optimizer/test/util.ts
+++ b/test/integration/image-optimizer/test/util.ts
@@ -36,6 +36,7 @@ type RunTestsCtx = SetupTestsCtx & {
nextOutput?: string
}
+let infiniteRedirect = 0
const largeSize = 1080 // defaults defined in server/config.ts
const animatedWarnText =
'is an animated image so it will not be optimized. Consider adding the "unoptimized" property to the .'
@@ -44,15 +45,32 @@ export async function serveSlowImage() {
const port = await findPort()
const server = http.createServer(async (req, res) => {
const parsedUrl = new URL(req.url, 'http://localhost')
- const delay = Number(parsedUrl.searchParams.get('delay')) || 500
+ const delay = Number(parsedUrl.searchParams.get('delay')) || 0
const status = Number(parsedUrl.searchParams.get('status')) || 200
+ const location = parsedUrl.searchParams.get('location')
console.log('delaying image for', delay)
await waitFor(delay)
res.statusCode = status
- if (status === 308) {
+ if (infiniteRedirect > 0 && infiniteRedirect < 1000) {
+ infiniteRedirect++
+ res.statusCode = 308
+ console.log('infinite redirect', location)
+ res.setHeader('location', '/')
+ res.end()
+ return
+ }
+
+ if (status === 301 && location) {
+ console.log('redirecting to location', location)
+ res.setHeader('location', location)
+ res.end()
+ return
+ }
+
+ if (status === 399) {
res.end('invalid status')
return
}
@@ -163,6 +181,8 @@ export function runTests(ctx: RunTestsCtx) {
domains = [],
formats = [],
minimumCacheTTL = 14400,
+ maximumRedirects = 3,
+ dangerouslyAllowLocalIP,
} = nextConfigImages || {}
const avifEnabled = formats[0] === 'image/avif'
let slowImageServer: Awaited>
@@ -173,9 +193,9 @@ export function runTests(ctx: RunTestsCtx) {
slowImageServer.stop()
})
- if (domains.length > 0) {
+ if (domains.length > 0 && dangerouslyAllowLocalIP) {
it('should normalize invalid status codes', async () => {
- const url = `http://localhost:${slowImageServer.port}/slow.png?delay=${1}&status=308`
+ const url = `http://localhost:${slowImageServer.port}/slow.png?status=399`
const query = { url, w: ctx.w, q: ctx.q }
const opts: RequestInit = {
headers: { accept: 'image/webp' },
@@ -194,6 +214,35 @@ export function runTests(ctx: RunTestsCtx) {
})
}
+ if (domains.length > 0) {
+ it('should follow redirect from http to https when maximumRedirects > 0', async () => {
+ const url = `http://image-optimization-test.vercel.app/frog.png`
+ const query = { url, w: ctx.w, q: ctx.q }
+ const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, {})
+ expect(res.status).toBe(maximumRedirects > 0 ? 200 : 508)
+ })
+
+ it('should follow redirect when dangerouslyAllowLocalIP enabled', async () => {
+ const url = `http://localhost:${slowImageServer.port}?status=301&location=%2Fslow.png`
+ const query = { url, w: ctx.w, q: ctx.q }
+ const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, {})
+ let expectedStatus = dangerouslyAllowLocalIP ? 200 : 400
+ if (maximumRedirects === 0) {
+ expectedStatus = 508
+ }
+ expect(res.status).toBe(expectedStatus)
+ })
+
+ it('should return 508 after redirecting too many times', async () => {
+ infiniteRedirect = 1
+ const url = `http://localhost:${slowImageServer.port}`
+ const query = { url, w: ctx.w, q: ctx.q }
+ const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, {})
+ expect(res.status).toBe(508)
+ infiniteRedirect = 0
+ })
+ }
+
it('should return home page', async () => {
const res = await fetchViaHTTP(ctx.appPort, '/', null, {})
expect(await res.text()).toMatch(/Image Optimizer Home/m)
@@ -887,7 +936,7 @@ export function runTests(ctx: RunTestsCtx) {
})
}
- if (domains.length > 0) {
+ if (domains.length > 0 && dangerouslyAllowLocalIP) {
it('should resize absolute url from localhost', async () => {
const url = `http://localhost:${ctx.appPort}/test.png`
const query = { url, w: ctx.w, q: ctx.q }
@@ -1043,7 +1092,7 @@ export function runTests(ctx: RunTestsCtx) {
}
it('should fail when url has file protocol', async () => {
- const url = `file://localhost:${ctx.appPort}/test.png`
+ const url = `file://example.vercel.sh:${ctx.appPort}/test.png`
const query = { url, w: ctx.w, q: ctx.q }
const opts = { headers: { accept: 'image/webp' } }
const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, opts)
@@ -1052,7 +1101,7 @@ export function runTests(ctx: RunTestsCtx) {
})
it('should fail when url has ftp protocol', async () => {
- const url = `ftp://localhost:${ctx.appPort}/test.png`
+ const url = `ftp://example.vercel.sh:${ctx.appPort}/test.png`
const query = { url, w: ctx.w, q: ctx.q }
const opts = { headers: { accept: 'image/webp' } }
const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, opts)
@@ -1068,7 +1117,7 @@ export function runTests(ctx: RunTestsCtx) {
})
it('should fail when url is protocol relative', async () => {
- const query = { url: `//example.com`, w: ctx.w, q: ctx.q }
+ const query = { url: `//example.vercel.sh`, w: ctx.w, q: ctx.q }
const res = await fetchViaHTTP(ctx.appPort, '/_next/image', query, {})
expect(res.status).toBe(400)
expect(await res.text()).toBe(
@@ -1139,7 +1188,7 @@ export function runTests(ctx: RunTestsCtx) {
)
})
- if (domains.length > 0) {
+ if (domains.length > 0 && dangerouslyAllowLocalIP) {
it('should fail when url fails to load an image', async () => {
const url = `http://localhost:${ctx.appPort}/not-an-image`
const query = { w: ctx.w, url, q: ctx.q }
@@ -1489,7 +1538,7 @@ export function runTests(ctx: RunTestsCtx) {
expect(await res.text()).toBe("The requested resource isn't a valid image.")
})
- if (domains.length > 0) {
+ if (domains.length > 0 && dangerouslyAllowLocalIP) {
it('should handle concurrent requests', async () => {
await cleanImagesDir(ctx.imagesDir)
const delay = 500
@@ -1614,6 +1663,7 @@ export const setupTests = (ctx: SetupTestsCtx) => {
q: 100,
isDev,
nextConfigImages: {
+ dangerouslyAllowLocalIP: true,
domains: [
'localhost',
'127.0.0.1',
@@ -1710,6 +1760,7 @@ export const setupTests = (ctx: SetupTestsCtx) => {
q: 100,
isDev,
nextConfigImages: {
+ dangerouslyAllowLocalIP: true,
domains: [
'localhost',
'127.0.0.1',
diff --git a/test/integration/next-image-new/app-dir-localpatterns/test/index.test.ts b/test/integration/next-image-new/app-dir-localpatterns/test/index.test.ts
index 30e4907ec04b9..8cfc8a713b552 100644
--- a/test/integration/next-image-new/app-dir-localpatterns/test/index.test.ts
+++ b/test/integration/next-image-new/app-dir-localpatterns/test/index.test.ts
@@ -75,6 +75,7 @@ function runTests(mode: 'dev' | 'server') {
contentDispositionType: 'attachment',
contentSecurityPolicy:
"script-src 'none'; frame-src 'none'; sandbox;",
+ dangerouslyAllowLocalIP: false,
dangerouslyAllowSVG: false,
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
disableStaticImages: false,
@@ -96,6 +97,7 @@ function runTests(mode: 'dev' | 'server') {
search: '',
},
],
+ maximumRedirects: 3,
minimumCacheTTL: 14400,
path: '/_next/image',
qualities: [75],
diff --git a/test/integration/next-image-new/app-dir-qualities/test/index.test.ts b/test/integration/next-image-new/app-dir-qualities/test/index.test.ts
index 67efd5f01a011..8589d740bd929 100644
--- a/test/integration/next-image-new/app-dir-qualities/test/index.test.ts
+++ b/test/integration/next-image-new/app-dir-qualities/test/index.test.ts
@@ -92,6 +92,7 @@ function runTests(mode: 'dev' | 'server') {
contentDispositionType: 'attachment',
contentSecurityPolicy:
"script-src 'none'; frame-src 'none'; sandbox;",
+ dangerouslyAllowLocalIP: false,
dangerouslyAllowSVG: false,
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
disableStaticImages: false,
@@ -108,6 +109,7 @@ function runTests(mode: 'dev' | 'server') {
search: '',
},
],
+ maximumRedirects: 3,
minimumCacheTTL: 14400,
path: '/_next/image',
qualities: [42, 69, 88],
diff --git a/test/integration/next-image-new/app-dir/test/index.test.ts b/test/integration/next-image-new/app-dir/test/index.test.ts
index c316d738c5b98..821982b6bb870 100644
--- a/test/integration/next-image-new/app-dir/test/index.test.ts
+++ b/test/integration/next-image-new/app-dir/test/index.test.ts
@@ -1778,6 +1778,7 @@ function runTests(mode: 'dev' | 'server') {
contentDispositionType: 'attachment',
contentSecurityPolicy:
"script-src 'none'; frame-src 'none'; sandbox;",
+ dangerouslyAllowLocalIP: false,
dangerouslyAllowSVG: false,
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
disableStaticImages: false,
@@ -1794,6 +1795,7 @@ function runTests(mode: 'dev' | 'server') {
search: '',
},
],
+ maximumRedirects: 3,
minimumCacheTTL: 14400,
path: '/_next/image',
qualities: [75],
diff --git a/test/integration/next-image-new/unicode/test/index.test.ts b/test/integration/next-image-new/unicode/test/index.test.ts
index 34c6996e43503..7d2beb43aa724 100644
--- a/test/integration/next-image-new/unicode/test/index.test.ts
+++ b/test/integration/next-image-new/unicode/test/index.test.ts
@@ -75,6 +75,7 @@ function runTests(mode: 'server' | 'dev') {
contentDispositionType: 'attachment',
contentSecurityPolicy:
"script-src 'none'; frame-src 'none'; sandbox;",
+ dangerouslyAllowLocalIP: false,
dangerouslyAllowSVG: false,
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
disableStaticImages: false,
@@ -101,6 +102,7 @@ function runTests(mode: 'server' | 'dev') {
search: '',
},
],
+ maximumRedirects: 3,
minimumCacheTTL: 14400,
path: '/_next/image',
qualities: [75],
diff --git a/test/integration/next-image-new/unoptimized/test/index.test.ts b/test/integration/next-image-new/unoptimized/test/index.test.ts
index 2304d3e784cd4..4c78061c99668 100644
--- a/test/integration/next-image-new/unoptimized/test/index.test.ts
+++ b/test/integration/next-image-new/unoptimized/test/index.test.ts
@@ -100,6 +100,7 @@ function runTests(url: string, mode: 'dev' | 'server') {
contentDispositionType: 'attachment',
contentSecurityPolicy:
"script-src 'none'; frame-src 'none'; sandbox;",
+ dangerouslyAllowLocalIP: false,
dangerouslyAllowSVG: false,
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
disableStaticImages: false,
@@ -116,6 +117,7 @@ function runTests(url: string, mode: 'dev' | 'server') {
search: '',
},
],
+ maximumRedirects: 3,
minimumCacheTTL: 14400,
path: '/_next/image',
qualities: [75],
diff --git a/test/production/app-dir/global-default-cache-handler/app/revalidate-tag/route.ts b/test/production/app-dir/global-default-cache-handler/app/revalidate-tag/route.ts
index 399578325a3d0..595c0d456bb85 100644
--- a/test/production/app-dir/global-default-cache-handler/app/revalidate-tag/route.ts
+++ b/test/production/app-dir/global-default-cache-handler/app/revalidate-tag/route.ts
@@ -4,7 +4,7 @@ import { NextRequest, NextResponse } from 'next/server'
export async function GET(req: NextRequest) {
console.log(req.url.toString())
- revalidateTag(req.nextUrl.searchParams.get('tag') || '')
+ revalidateTag(req.nextUrl.searchParams.get('tag') || '', 'expireNow')
return NextResponse.json({ success: true })
}
diff --git a/test/production/app-dir/global-default-cache-handler/global-default-cache-handler.test.ts b/test/production/app-dir/global-default-cache-handler/global-default-cache-handler.test.ts
index bf7f79e2414b3..3cababab9493f 100644
--- a/test/production/app-dir/global-default-cache-handler/global-default-cache-handler.test.ts
+++ b/test/production/app-dir/global-default-cache-handler/global-default-cache-handler.test.ts
@@ -43,8 +43,8 @@ describe('global-default-cache-handler', () => {
console.log('symbol getExpiration', tags)
},
- expireTags(...tags) {
- console.log('symbol expireTags', tags)
+ updateTags(...tags) {
+ console.log('symbol updateTags', tags)
}
}
}
@@ -93,12 +93,12 @@ describe('global-default-cache-handler', () => {
})
})
- it('should call expireTags on global default cache handler', async () => {
+ it('should call updateTags on global default cache handler', async () => {
const res = await fetchViaHTTP(appPort, '/revalidate-tag', { tag: 'tag1' })
expect(res.status).toBe(200)
await retry(() => {
- expect(output).toContain('symbol expireTags')
+ expect(output).toContain('symbol updateTags')
expect(output).toContain('tag1')
})
})
diff --git a/test/production/app-dir/global-default-cache-handler/next.config.js b/test/production/app-dir/global-default-cache-handler/next.config.js
index 5bf8b9f6b99f5..3da611fa376bc 100644
--- a/test/production/app-dir/global-default-cache-handler/next.config.js
+++ b/test/production/app-dir/global-default-cache-handler/next.config.js
@@ -5,6 +5,13 @@ const nextConfig = {
output: 'standalone',
experimental: {
useCache: true,
+ cacheLife: {
+ expireNow: {
+ stale: 0,
+ expire: 0,
+ revalidate: 0,
+ },
+ },
},
}
diff --git a/test/production/app-dir/parallel-routes-static/app/nested/@bar/default.tsx b/test/production/app-dir/parallel-routes-static/app/nested/@bar/default.tsx
new file mode 100644
index 0000000000000..6dbe479afc29b
--- /dev/null
+++ b/test/production/app-dir/parallel-routes-static/app/nested/@bar/default.tsx
@@ -0,0 +1,5 @@
+import { notFound } from 'next/navigation'
+
+export default function Default() {
+ notFound()
+}
diff --git a/test/production/app-dir/parallel-routes-static/app/nested/@foo/default.tsx b/test/production/app-dir/parallel-routes-static/app/nested/@foo/default.tsx
new file mode 100644
index 0000000000000..6dbe479afc29b
--- /dev/null
+++ b/test/production/app-dir/parallel-routes-static/app/nested/@foo/default.tsx
@@ -0,0 +1,5 @@
+import { notFound } from 'next/navigation'
+
+export default function Default() {
+ notFound()
+}
diff --git a/test/production/app-dir/resume-data-cache/app/revalidate/route.ts b/test/production/app-dir/resume-data-cache/app/revalidate/route.ts
index 4100bb53cdd06..e26460e8628b0 100644
--- a/test/production/app-dir/resume-data-cache/app/revalidate/route.ts
+++ b/test/production/app-dir/resume-data-cache/app/revalidate/route.ts
@@ -1,6 +1,6 @@
import { revalidateTag } from 'next/cache'
export function POST() {
- revalidateTag('test')
+ revalidateTag('test', 'expireNow')
return new Response(null, { status: 200 })
}
diff --git a/test/production/app-dir/resume-data-cache/next.config.js b/test/production/app-dir/resume-data-cache/next.config.js
index cf8a60b4804fc..d875a2fbebf6e 100644
--- a/test/production/app-dir/resume-data-cache/next.config.js
+++ b/test/production/app-dir/resume-data-cache/next.config.js
@@ -6,6 +6,13 @@ const nextConfig = {
cacheComponents: true,
clientSegmentCache: true,
clientParamParsing: true,
+ cacheLife: {
+ expireNow: {
+ stale: 0,
+ expire: 0,
+ revalidate: 0,
+ },
+ },
},
}
diff --git a/test/production/app-dir/ssg-single-pass/app/revalidate/route.ts b/test/production/app-dir/ssg-single-pass/app/revalidate/route.ts
index 6394d3d69efff..2d1d363f655c8 100644
--- a/test/production/app-dir/ssg-single-pass/app/revalidate/route.ts
+++ b/test/production/app-dir/ssg-single-pass/app/revalidate/route.ts
@@ -1,8 +1,8 @@
import { NextResponse } from 'next/server'
-import { unstable_expirePath } from 'next/cache'
+import { revalidatePath } from 'next/cache'
export async function GET() {
- unstable_expirePath('/')
+ revalidatePath('/')
return NextResponse.json({ success: true })
}
diff --git a/test/production/custom-server/cache-handler.js b/test/production/custom-server/cache-handler.js
index 283beaa1f3ab4..6ee7e200fccf2 100644
--- a/test/production/custom-server/cache-handler.js
+++ b/test/production/custom-server/cache-handler.js
@@ -6,7 +6,7 @@ const defaultCacheHandler =
require('next/dist/server/lib/cache-handlers/default.external').default
/**
- * @type {import('next/dist/server/lib/cache-handlers/types').CacheHandlerV2}
+ * @type {import('next/dist/server/lib/cache-handlers/types').CacheHandler}
*/
const cacheHandler = {
async get(cacheKey) {
@@ -23,12 +23,12 @@ const cacheHandler = {
return defaultCacheHandler.refreshTags()
},
- async getExpiration(...tags) {
- return defaultCacheHandler.getExpiration(...tags)
+ async getExpiration(tags) {
+ return defaultCacheHandler.getExpiration(tags)
},
- async expireTags(...tags) {
- return defaultCacheHandler.expireTags(...tags)
+ async updateTags(tags) {
+ return defaultCacheHandler.updateTags(tags)
},
}
diff --git a/test/production/next-server-nft/next-server-nft.test.ts b/test/production/next-server-nft/next-server-nft.test.ts
index 1c98f5e5f76b1..ea49dc5a59732 100644
--- a/test/production/next-server-nft/next-server-nft.test.ts
+++ b/test/production/next-server-nft/next-server-nft.test.ts
@@ -138,6 +138,7 @@ const isReact18 = parseInt(process.env.NEXT_TEST_REACT_VERSION) === 18
"/node_modules/next/dist/compiled/image-detector/detector.js",
"/node_modules/next/dist/compiled/image-size/index.js",
"/node_modules/next/dist/compiled/is-animated/index.js",
+ "/node_modules/next/dist/compiled/is-local-address/index.js",
"/node_modules/next/dist/compiled/jsonwebtoken/index.js",
"/node_modules/next/dist/compiled/nanoid/index.cjs",
"/node_modules/next/dist/compiled/next-server/app-page-turbo-experimental.runtime.prod.js",
diff --git a/test/rspack-build-tests-manifest.json b/test/rspack-build-tests-manifest.json
index b9dea3b9b53d9..f0615fd513ac8 100644
--- a/test/rspack-build-tests-manifest.json
+++ b/test/rspack-build-tests-manifest.json
@@ -165,8 +165,8 @@
"app-dir action handling fetch actions should handle calls to redirect() with a relative URL in a single pass",
"app-dir action handling fetch actions should handle calls to redirect() with external URLs",
"app-dir action handling fetch actions should handle redirects to routes that provide an invalid RSC response",
- "app-dir action handling fetch actions should handle unstable_expirePath",
- "app-dir action handling fetch actions should handle unstable_expireTag",
+ "app-dir action handling fetch actions should handle revalidatePath",
+ "app-dir action handling fetch actions should handle revalidateTag",
"app-dir action handling fetch actions should invalidate client cache on other routes when cookies.set is called",
"app-dir action handling fetch actions should invalidate client cache when path is revalidated",
"app-dir action handling fetch actions should invalidate client cache when tag is revalidated",
@@ -228,7 +228,7 @@
],
"failed": [],
"pending": [
- "app-dir action handling fetch actions should handle unstable_expireTag + redirect",
+ "app-dir action handling fetch actions should handle revalidateTag + redirect",
"app-dir action handling server actions render client components client component imported action should support importing client components from actions"
],
"flakey": [],
@@ -299,8 +299,8 @@
"app-dir action handling fetch actions should handle calls to redirect() with a relative URL in a single pass",
"app-dir action handling fetch actions should handle calls to redirect() with external URLs",
"app-dir action handling fetch actions should handle redirects to routes that provide an invalid RSC response",
- "app-dir action handling fetch actions should handle unstable_expirePath",
- "app-dir action handling fetch actions should handle unstable_expireTag",
+ "app-dir action handling fetch actions should handle revalidatePath",
+ "app-dir action handling fetch actions should handle revalidateTag",
"app-dir action handling fetch actions should invalidate client cache on other routes when cookies.set is called",
"app-dir action handling fetch actions should invalidate client cache when path is revalidated",
"app-dir action handling fetch actions should invalidate client cache when tag is revalidated",
@@ -362,7 +362,7 @@
],
"failed": [],
"pending": [
- "app-dir action handling fetch actions should handle unstable_expireTag + redirect",
+ "app-dir action handling fetch actions should handle revalidateTag + redirect",
"app-dir action handling server actions render client components client component imported action should support importing client components from actions"
],
"flakey": [],
@@ -5729,7 +5729,7 @@
},
"test/e2e/app-dir/revalidate-dynamic/revalidate-dynamic.test.ts": {
"passed": [
- "app-dir revalidate-dynamic should correctly mark a route handler that uses unstable_expireTag as dynamic",
+ "app-dir revalidate-dynamic should correctly mark a route handler that uses revalidateTag as dynamic",
"app-dir revalidate-dynamic should revalidate the data with /api/revalidate-path",
"app-dir revalidate-dynamic should revalidate the data with /api/revalidate-tag"
],
@@ -5740,8 +5740,8 @@
},
"test/e2e/app-dir/revalidatetag-rsc/revalidatetag-rsc.test.ts": {
"passed": [
- "unstable_expireTag-rsc should error if unstable_expireTag is called during render",
- "unstable_expireTag-rsc should revalidate fetch cache if unstable_expireTag invoked via server action"
+ "revalidateTag-rsc should error if revalidateTag is called during render",
+ "revalidateTag-rsc should revalidate fetch cache if revalidateTag invoked via server action"
],
"failed": [],
"pending": [],
@@ -7132,7 +7132,7 @@
"test/e2e/app-dir/use-cache-custom-handler/use-cache-custom-handler.test.ts": {
"passed": [
"use-cache-custom-handler calls neither refreshTags nor getExpiration if \"use cache\" is not used",
- "use-cache-custom-handler should not call expireTags for a normal invocation",
+ "use-cache-custom-handler should not call updateTags for a normal invocation",
"use-cache-custom-handler should not call getExpiration after an action",
"use-cache-custom-handler should revalidate after redirect using a legacy custom cache handler",
"use-cache-custom-handler should revalidate after redirect using a modern custom cache handler",
@@ -7260,7 +7260,7 @@
"use-cache can reference server actions in \"use cache\" functions",
"use-cache renders the not-found page when `notFound()` is used",
"use-cache shares caches between the page/layout and generateMetadata",
- "use-cache should be able to revalidate a page using unstable_expireTag",
+ "use-cache should be able to revalidate a page using revalidateTag",
"use-cache should cache complex args",
"use-cache should cache fetch without no-store",
"use-cache should cache results",
@@ -7290,7 +7290,7 @@
"use-cache should revalidate caches nested in unstable_cache",
"use-cache should send an SWR cache-control header based on the revalidate and expire values",
"use-cache should store a fetch response without no-store in the incremental cache handler during build",
- "use-cache should update after unstable_expireTag correctly",
+ "use-cache should update after revalidateTag correctly",
"use-cache should use revalidate config in fetch",
"use-cache usage in node_modules should cache results when using a directive with a handler",
"use-cache usage in node_modules should cache results when using a directive without a handler",
@@ -19999,7 +19999,7 @@
},
"test/production/app-dir/global-default-cache-handler/global-default-cache-handler.test.ts": {
"passed": [
- "global-default-cache-handler should call expireTags on global default cache handler",
+ "global-default-cache-handler should call updateTags on global default cache handler",
"global-default-cache-handler should call refreshTags on global default cache handler",
"global-default-cache-handler should use global symbol for default cache handler"
],
diff --git a/test/rspack-dev-tests-manifest.json b/test/rspack-dev-tests-manifest.json
index 133d15bc3d24a..d52767cb457fd 100644
--- a/test/rspack-dev-tests-manifest.json
+++ b/test/rspack-dev-tests-manifest.json
@@ -221,8 +221,8 @@
"Error overlay - RSC build errors importing 'next/cache' APIs in a client component unstable_cache is allowed",
"Error overlay - RSC build errors importing 'next/cache' APIs in a client component unstable_cacheLife is not allowed",
"Error overlay - RSC build errors importing 'next/cache' APIs in a client component unstable_cacheTag is not allowed",
- "Error overlay - RSC build errors importing 'next/cache' APIs in a client component unstable_expirePath is not allowed",
- "Error overlay - RSC build errors importing 'next/cache' APIs in a client component unstable_expireTag is not allowed",
+ "Error overlay - RSC build errors importing 'next/cache' APIs in a client component revalidatePath is not allowed",
+ "Error overlay - RSC build errors importing 'next/cache' APIs in a client component revalidateTag is not allowed",
"Error overlay - RSC build errors importing 'next/cache' APIs in a client component unstable_noStore is allowed",
"Error overlay - RSC build errors next/root-params importing 'next/root-params' in a client component",
"Error overlay - RSC build errors next/root-params importing 'next/root-params' in a client component in a way that bypasses import analysis",
@@ -467,8 +467,8 @@
"Error Overlay for server components compiler errors in pages importing 'next/cache' APIs in pages unstable_cache is allowed",
"Error Overlay for server components compiler errors in pages importing 'next/cache' APIs in pages unstable_cacheLife is not allowed",
"Error Overlay for server components compiler errors in pages importing 'next/cache' APIs in pages unstable_cacheTag is not allowed",
- "Error Overlay for server components compiler errors in pages importing 'next/cache' APIs in pages unstable_expirePath is not allowed",
- "Error Overlay for server components compiler errors in pages importing 'next/cache' APIs in pages unstable_expireTag is not allowed",
+ "Error Overlay for server components compiler errors in pages importing 'next/cache' APIs in pages revalidatePath is not allowed",
+ "Error Overlay for server components compiler errors in pages importing 'next/cache' APIs in pages revalidateTag is not allowed",
"Error Overlay for server components compiler errors in pages importing 'next/cache' APIs in pages unstable_noStore is allowed",
"Error Overlay for server components compiler errors in pages importing 'next/headers' in pages",
"Error Overlay for server components compiler errors in pages importing 'next/root-params' in pages",
@@ -2613,8 +2613,8 @@
"app-dir action handling fetch actions should handle calls to redirect() with a relative URL in a single pass",
"app-dir action handling fetch actions should handle calls to redirect() with external URLs",
"app-dir action handling fetch actions should handle redirects to routes that provide an invalid RSC response",
- "app-dir action handling fetch actions should handle unstable_expirePath",
- "app-dir action handling fetch actions should handle unstable_expireTag",
+ "app-dir action handling fetch actions should handle revalidatePath",
+ "app-dir action handling fetch actions should handle revalidateTag",
"app-dir action handling fetch actions should invalidate client cache on other routes when cookies.set is called",
"app-dir action handling fetch actions should invalidate client cache when path is revalidated",
"app-dir action handling fetch actions should invalidate client cache when tag is revalidated",
@@ -2675,7 +2675,7 @@
],
"failed": [],
"pending": [
- "app-dir action handling fetch actions should handle unstable_expireTag + redirect",
+ "app-dir action handling fetch actions should handle revalidateTag + redirect",
"app-dir action handling server actions render client components client component imported action should support importing client components from actions"
],
"flakey": [],
@@ -2742,8 +2742,8 @@
"app-dir action handling fetch actions should handle calls to redirect() with a relative URL in a single pass",
"app-dir action handling fetch actions should handle calls to redirect() with external URLs",
"app-dir action handling fetch actions should handle redirects to routes that provide an invalid RSC response",
- "app-dir action handling fetch actions should handle unstable_expirePath",
- "app-dir action handling fetch actions should handle unstable_expireTag",
+ "app-dir action handling fetch actions should handle revalidatePath",
+ "app-dir action handling fetch actions should handle revalidateTag",
"app-dir action handling fetch actions should invalidate client cache on other routes when cookies.set is called",
"app-dir action handling fetch actions should invalidate client cache when path is revalidated",
"app-dir action handling fetch actions should invalidate client cache when tag is revalidated",
@@ -2804,7 +2804,7 @@
],
"failed": [],
"pending": [
- "app-dir action handling fetch actions should handle unstable_expireTag + redirect",
+ "app-dir action handling fetch actions should handle revalidateTag + redirect",
"app-dir action handling server actions render client components client component imported action should support importing client components from actions"
],
"flakey": [],
@@ -7733,8 +7733,8 @@
},
"test/e2e/app-dir/revalidatetag-rsc/revalidatetag-rsc.test.ts": {
"passed": [
- "unstable_expireTag-rsc should error if unstable_expireTag is called during render",
- "unstable_expireTag-rsc should revalidate fetch cache if unstable_expireTag invoked via server action"
+ "revalidateTag-rsc should error if revalidateTag is called during render",
+ "revalidateTag-rsc should revalidate fetch cache if revalidateTag invoked via server action"
],
"failed": [],
"pending": [],
@@ -8984,7 +8984,7 @@
"test/e2e/app-dir/use-cache-custom-handler/use-cache-custom-handler.test.ts": {
"passed": [
"use-cache-custom-handler calls neither refreshTags nor getExpiration if \"use cache\" is not used",
- "use-cache-custom-handler should not call expireTags for a normal invocation",
+ "use-cache-custom-handler should not call updateTags for a normal invocation",
"use-cache-custom-handler should not call getExpiration after an action",
"use-cache-custom-handler should revalidate after redirect using a legacy custom cache handler",
"use-cache-custom-handler should revalidate after redirect using a modern custom cache handler",
@@ -9122,7 +9122,7 @@
"use-cache renders the not-found page when `notFound()` is used",
"use-cache replays logs from \"use cache\" functions",
"use-cache shares caches between the page/layout and generateMetadata",
- "use-cache should be able to revalidate a page using unstable_expireTag",
+ "use-cache should be able to revalidate a page using revalidateTag",
"use-cache should cache complex args",
"use-cache should cache fetch without no-store",
"use-cache should cache results",
@@ -9145,7 +9145,7 @@
"use-cache should revalidate caches after redirect",
"use-cache should revalidate caches during on-demand revalidation",
"use-cache should revalidate caches nested in unstable_cache",
- "use-cache should update after unstable_expireTag correctly",
+ "use-cache should update after revalidateTag correctly",
"use-cache should use revalidate config in fetch",
"use-cache usage in node_modules should cache results when using a directive with a handler",
"use-cache usage in node_modules should cache results when using a directive without a handler",
diff --git a/test/turbopack-build-tests-manifest.json b/test/turbopack-build-tests-manifest.json
index 2d0f6ad28dfa1..74124d0bf09ac 100644
--- a/test/turbopack-build-tests-manifest.json
+++ b/test/turbopack-build-tests-manifest.json
@@ -162,8 +162,8 @@
"app-dir action handling fetch actions should handle calls to redirect() with a relative URL in a single pass",
"app-dir action handling fetch actions should handle calls to redirect() with external URLs",
"app-dir action handling fetch actions should handle redirects to routes that provide an invalid RSC response",
- "app-dir action handling fetch actions should handle unstable_expirePath",
- "app-dir action handling fetch actions should handle unstable_expireTag",
+ "app-dir action handling fetch actions should handle revalidatePath",
+ "app-dir action handling fetch actions should handle revalidateTag",
"app-dir action handling fetch actions should invalidate client cache on other routes when cookies.set is called",
"app-dir action handling fetch actions should invalidate client cache when path is revalidated",
"app-dir action handling fetch actions should invalidate client cache when tag is revalidated",
@@ -225,7 +225,7 @@
],
"failed": [],
"pending": [
- "app-dir action handling fetch actions should handle unstable_expireTag + redirect",
+ "app-dir action handling fetch actions should handle revalidateTag + redirect",
"app-dir action handling server actions render client components client component imported action should support importing client components from actions"
],
"flakey": [],
@@ -294,8 +294,8 @@
"app-dir action handling fetch actions should handle calls to redirect() with a relative URL in a single pass",
"app-dir action handling fetch actions should handle calls to redirect() with external URLs",
"app-dir action handling fetch actions should handle redirects to routes that provide an invalid RSC response",
- "app-dir action handling fetch actions should handle unstable_expirePath",
- "app-dir action handling fetch actions should handle unstable_expireTag",
+ "app-dir action handling fetch actions should handle revalidatePath",
+ "app-dir action handling fetch actions should handle revalidateTag",
"app-dir action handling fetch actions should invalidate client cache on other routes when cookies.set is called",
"app-dir action handling fetch actions should invalidate client cache when path is revalidated",
"app-dir action handling fetch actions should invalidate client cache when tag is revalidated",
@@ -357,7 +357,7 @@
],
"failed": [],
"pending": [
- "app-dir action handling fetch actions should handle unstable_expireTag + redirect",
+ "app-dir action handling fetch actions should handle revalidateTag + redirect",
"app-dir action handling server actions render client components client component imported action should support importing client components from actions"
],
"flakey": [],
@@ -4776,7 +4776,7 @@
},
"test/e2e/app-dir/revalidate-dynamic/revalidate-dynamic.test.ts": {
"passed": [
- "app-dir revalidate-dynamic should correctly mark a route handler that uses unstable_expireTag as dynamic",
+ "app-dir revalidate-dynamic should correctly mark a route handler that uses revalidateTag as dynamic",
"app-dir revalidate-dynamic should revalidate the data with /api/revalidate-path",
"app-dir revalidate-dynamic should revalidate the data with /api/revalidate-tag"
],
@@ -4787,8 +4787,8 @@
},
"test/e2e/app-dir/revalidatetag-rsc/revalidatetag-rsc.test.ts": {
"passed": [
- "unstable_expireTag-rsc should error if unstable_expireTag is called during render",
- "unstable_expireTag-rsc should revalidate fetch cache if unstable_expireTag invoked via server action"
+ "revalidateTag-rsc should error if revalidateTag is called during render",
+ "revalidateTag-rsc should revalidate fetch cache if revalidateTag invoked via server action"
],
"failed": [],
"pending": [],
@@ -5950,7 +5950,7 @@
"test/e2e/app-dir/use-cache-custom-handler/use-cache-custom-handler.test.ts": {
"passed": [
"use-cache-custom-handler calls neither refreshTags nor getExpiration if \"use cache\" is not used",
- "use-cache-custom-handler should not call expireTags for a normal invocation",
+ "use-cache-custom-handler should not call updateTags for a normal invocation",
"use-cache-custom-handler should not call getExpiration after an action",
"use-cache-custom-handler should revalidate after redirect using a legacy custom cache handler",
"use-cache-custom-handler should revalidate after redirect using a modern custom cache handler",
@@ -6052,7 +6052,7 @@
"use-cache can reference server actions in \"use cache\" functions",
"use-cache renders the not-found page when `notFound()` is used",
"use-cache shares caches between the page/layout and generateMetadata",
- "use-cache should be able to revalidate a page using unstable_expireTag",
+ "use-cache should be able to revalidate a page using revalidateTag",
"use-cache should cache complex args",
"use-cache should cache fetch without no-store",
"use-cache should cache results",
@@ -6079,7 +6079,7 @@
"use-cache should revalidate caches nested in unstable_cache",
"use-cache should send an SWR cache-control header based on the revalidate and expire values",
"use-cache should store a fetch response without no-store in the incremental cache handler during build",
- "use-cache should update after unstable_expireTag correctly",
+ "use-cache should update after revalidateTag correctly",
"use-cache should use revalidate config in fetch",
"use-cache usage in node_modules should cache results when using a directive with a handler",
"use-cache usage in node_modules should cache results when using a directive without a handler",
@@ -18427,7 +18427,7 @@
},
"test/production/app-dir/global-default-cache-handler/global-default-cache-handler.test.ts": {
"passed": [
- "global-default-cache-handler should call expireTags on global default cache handler",
+ "global-default-cache-handler should call updateTags on global default cache handler",
"global-default-cache-handler should call refreshTags on global default cache handler",
"global-default-cache-handler should use global symbol for default cache handler"
],
diff --git a/test/turbopack-dev-tests-manifest.json b/test/turbopack-dev-tests-manifest.json
index 1acad1033dc01..15665e2de480a 100644
--- a/test/turbopack-dev-tests-manifest.json
+++ b/test/turbopack-dev-tests-manifest.json
@@ -2020,8 +2020,8 @@
"Error overlay - RSC build errors importing 'next/cache' APIs in a client component unstable_cache is allowed",
"Error overlay - RSC build errors importing 'next/cache' APIs in a client component unstable_cacheLife is not allowed",
"Error overlay - RSC build errors importing 'next/cache' APIs in a client component unstable_cacheTag is not allowed",
- "Error overlay - RSC build errors importing 'next/cache' APIs in a client component unstable_expirePath is not allowed",
- "Error overlay - RSC build errors importing 'next/cache' APIs in a client component unstable_expireTag is not allowed",
+ "Error overlay - RSC build errors importing 'next/cache' APIs in a client component revalidatePath is not allowed",
+ "Error overlay - RSC build errors importing 'next/cache' APIs in a client component revalidateTag is not allowed",
"Error overlay - RSC build errors importing 'next/cache' APIs in a client component unstable_noStore is allowed",
"Error overlay - RSC build errors should allow to use and handle rsc poisoning client-only",
"Error overlay - RSC build errors should allow to use and handle rsc poisoning server-only",
@@ -2275,8 +2275,8 @@
"Error Overlay for server components compiler errors in pages importing 'next/cache' APIs in pages unstable_cache is allowed",
"Error Overlay for server components compiler errors in pages importing 'next/cache' APIs in pages unstable_cacheLife is not allowed",
"Error Overlay for server components compiler errors in pages importing 'next/cache' APIs in pages unstable_cacheTag is not allowed",
- "Error Overlay for server components compiler errors in pages importing 'next/cache' APIs in pages unstable_expirePath is not allowed",
- "Error Overlay for server components compiler errors in pages importing 'next/cache' APIs in pages unstable_expireTag is not allowed",
+ "Error Overlay for server components compiler errors in pages importing 'next/cache' APIs in pages revalidatePath is not allowed",
+ "Error Overlay for server components compiler errors in pages importing 'next/cache' APIs in pages revalidateTag is not allowed",
"Error Overlay for server components compiler errors in pages importing 'next/cache' APIs in pages unstable_noStore is allowed",
"Error Overlay for server components compiler errors in pages importing 'next/headers' in pages",
"Error Overlay for server components compiler errors in pages importing 'server-only' in pages",
@@ -4216,8 +4216,8 @@
"app-dir action handling fetch actions should handle calls to redirect() with a relative URL in a single pass",
"app-dir action handling fetch actions should handle calls to redirect() with external URLs",
"app-dir action handling fetch actions should handle redirects to routes that provide an invalid RSC response",
- "app-dir action handling fetch actions should handle unstable_expirePath",
- "app-dir action handling fetch actions should handle unstable_expireTag",
+ "app-dir action handling fetch actions should handle revalidatePath",
+ "app-dir action handling fetch actions should handle revalidateTag",
"app-dir action handling fetch actions should invalidate client cache on other routes when cookies.set is called",
"app-dir action handling fetch actions should invalidate client cache when path is revalidated",
"app-dir action handling fetch actions should invalidate client cache when tag is revalidated",
@@ -4279,7 +4279,7 @@
],
"failed": [],
"pending": [
- "app-dir action handling fetch actions should handle unstable_expireTag + redirect",
+ "app-dir action handling fetch actions should handle revalidateTag + redirect",
"app-dir action handling server actions render client components client component imported action should support importing client components from actions"
],
"flakey": [],
@@ -4344,8 +4344,8 @@
"app-dir action handling fetch actions should handle calls to redirect() with a relative URL in a single pass",
"app-dir action handling fetch actions should handle calls to redirect() with external URLs",
"app-dir action handling fetch actions should handle redirects to routes that provide an invalid RSC response",
- "app-dir action handling fetch actions should handle unstable_expirePath",
- "app-dir action handling fetch actions should handle unstable_expireTag",
+ "app-dir action handling fetch actions should handle revalidatePath",
+ "app-dir action handling fetch actions should handle revalidateTag",
"app-dir action handling fetch actions should invalidate client cache on other routes when cookies.set is called",
"app-dir action handling fetch actions should invalidate client cache when path is revalidated",
"app-dir action handling fetch actions should invalidate client cache when tag is revalidated",
@@ -4407,7 +4407,7 @@
],
"failed": [],
"pending": [
- "app-dir action handling fetch actions should handle unstable_expireTag + redirect",
+ "app-dir action handling fetch actions should handle revalidateTag + redirect",
"app-dir action handling server actions render client components client component imported action should support importing client components from actions"
],
"flakey": [],
@@ -8399,8 +8399,8 @@
},
"test/e2e/app-dir/revalidatetag-rsc/revalidatetag-rsc.test.ts": {
"passed": [
- "unstable_expireTag-rsc should error if unstable_expireTag is called during render",
- "unstable_expireTag-rsc should revalidate fetch cache if unstable_expireTag invoked via server action"
+ "revalidateTag-rsc should error if revalidateTag is called during render",
+ "revalidateTag-rsc should revalidate fetch cache if revalidateTag invoked via server action"
],
"failed": [],
"pending": [],
@@ -9502,7 +9502,7 @@
"test/e2e/app-dir/use-cache-custom-handler/use-cache-custom-handler.test.ts": {
"passed": [
"use-cache-custom-handler calls neither refreshTags nor getExpiration if \"use cache\" is not used",
- "use-cache-custom-handler should not call expireTags for a normal invocation",
+ "use-cache-custom-handler should not call updateTags for a normal invocation",
"use-cache-custom-handler should not call getExpiration after an action",
"use-cache-custom-handler should revalidate after redirect using a legacy custom cache handler",
"use-cache-custom-handler should revalidate after redirect using a modern custom cache handler",
@@ -9619,7 +9619,7 @@
"use-cache renders the not-found page when `notFound()` is used",
"use-cache replays logs from \"use cache\" functions",
"use-cache shares caches between the page/layout and generateMetadata",
- "use-cache should be able to revalidate a page using unstable_expireTag",
+ "use-cache should be able to revalidate a page using revalidateTag",
"use-cache should cache complex args",
"use-cache should cache fetch without no-store",
"use-cache should cache results",
@@ -9641,7 +9641,7 @@
"use-cache should revalidate caches after redirect",
"use-cache should revalidate caches during on-demand revalidation",
"use-cache should revalidate caches nested in unstable_cache",
- "use-cache should update after unstable_expireTag correctly",
+ "use-cache should update after revalidateTag correctly",
"use-cache should use revalidate config in fetch",
"use-cache usage in node_modules should cache results when using a directive with a handler",
"use-cache usage in node_modules should cache results when using a directive without a handler",
diff --git a/test/unit/eslint-plugin-next/with-app-dir/app/@modal/default.tsx b/test/unit/eslint-plugin-next/with-app-dir/app/@modal/default.tsx
new file mode 100644
index 0000000000000..6dbe479afc29b
--- /dev/null
+++ b/test/unit/eslint-plugin-next/with-app-dir/app/@modal/default.tsx
@@ -0,0 +1,5 @@
+import { notFound } from 'next/navigation'
+
+export default function Default() {
+ notFound()
+}