diff --git a/test/e2e/app-dir/use-selected-layout-segment-s/app/layout.tsx b/test/e2e/app-dir/use-selected-layout-segment-s/app/layout.tsx
new file mode 100644
index 000000000000..4013c87af92f
--- /dev/null
+++ b/test/e2e/app-dir/use-selected-layout-segment-s/app/layout.tsx
@@ -0,0 +1,29 @@
+import Link from 'next/link'
+import RenderValues from './render-values'
+
+export default function Layout({ children }: { children: React.ReactNode }) {
+ return (
+
+
+
+
+ Change static
+
+
+ Change param
+
+
+ Change param
+
+ {children}
+
+
+ )
+}
diff --git a/test/e2e/app-dir/use-selected-layout-segment-s/app/render-values.tsx b/test/e2e/app-dir/use-selected-layout-segment-s/app/render-values.tsx
new file mode 100644
index 000000000000..cb2cc8ddbfdb
--- /dev/null
+++ b/test/e2e/app-dir/use-selected-layout-segment-s/app/render-values.tsx
@@ -0,0 +1,19 @@
+'use client'
+
+import {
+ useSelectedLayoutSegment,
+ useSelectedLayoutSegments,
+} from 'next/navigation'
+
+export default function RenderValues({ prefix }: { prefix: string }) {
+ return (
+
+
+ {JSON.stringify(useSelectedLayoutSegments())}
+
+
+ {JSON.stringify(useSelectedLayoutSegment())}
+
+
+ )
+}
diff --git a/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/different-segment/page.tsx b/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/different-segment/page.tsx
new file mode 100644
index 000000000000..c17431379f96
--- /dev/null
+++ b/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/different-segment/page.tsx
@@ -0,0 +1,3 @@
+export default function Page() {
+ return null
+}
diff --git a/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/layout.tsx b/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/layout.tsx
new file mode 100644
index 000000000000..fd9a887f558b
--- /dev/null
+++ b/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/layout.tsx
@@ -0,0 +1,10 @@
+import RenderValues from '../../render-values'
+
+export default function Layout({ children }: { children: React.ReactNode }) {
+ return (
+ <>
+
+ {children}
+ >
+ )
+}
diff --git a/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/segment-name2/[param2]/[...catchall]/layout.tsx b/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/segment-name2/[param2]/[...catchall]/layout.tsx
new file mode 100644
index 000000000000..0cc7c3bd980c
--- /dev/null
+++ b/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/segment-name2/[param2]/[...catchall]/layout.tsx
@@ -0,0 +1,10 @@
+import RenderValues from '../../../../../render-values'
+
+export default function Layout({ children }: { children: React.ReactNode }) {
+ return (
+ <>
+
+ {children}
+ >
+ )
+}
diff --git a/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/segment-name2/[param2]/[...catchall]/page.tsx b/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/segment-name2/[param2]/[...catchall]/page.tsx
new file mode 100644
index 000000000000..c17431379f96
--- /dev/null
+++ b/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/segment-name2/[param2]/[...catchall]/page.tsx
@@ -0,0 +1,3 @@
+export default function Page() {
+ return null
+}
diff --git a/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/segment-name2/[param2]/layout.tsx b/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/segment-name2/[param2]/layout.tsx
new file mode 100644
index 000000000000..1b27aa42497f
--- /dev/null
+++ b/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/segment-name2/[param2]/layout.tsx
@@ -0,0 +1,10 @@
+import RenderValues from '../../../../render-values'
+
+export default function Layout({ children }: { children: React.ReactNode }) {
+ return (
+ <>
+
+ {children}
+ >
+ )
+}
diff --git a/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/segment-name2/layout.tsx b/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/segment-name2/layout.tsx
new file mode 100644
index 000000000000..a256a87f595f
--- /dev/null
+++ b/test/e2e/app-dir/use-selected-layout-segment-s/app/segment-name/[param1]/segment-name2/layout.tsx
@@ -0,0 +1,10 @@
+import RenderValues from '../../../render-values'
+
+export default function Layout({ children }: { children: React.ReactNode }) {
+ return (
+ <>
+
+ {children}
+ >
+ )
+}
diff --git a/test/e2e/app-dir/use-selected-layout-segment-s/next.config.js b/test/e2e/app-dir/use-selected-layout-segment-s/next.config.js
new file mode 100644
index 000000000000..cfa3ac3d7aa9
--- /dev/null
+++ b/test/e2e/app-dir/use-selected-layout-segment-s/next.config.js
@@ -0,0 +1,5 @@
+module.exports = {
+ experimental: {
+ appDir: true,
+ },
+}
diff --git a/test/e2e/app-dir/use-selected-layout-segment-s/use-selected-layout-segment-s.test.ts b/test/e2e/app-dir/use-selected-layout-segment-s/use-selected-layout-segment-s.test.ts
new file mode 100644
index 000000000000..12410ceb089b
--- /dev/null
+++ b/test/e2e/app-dir/use-selected-layout-segment-s/use-selected-layout-segment-s.test.ts
@@ -0,0 +1,141 @@
+import { createNext, FileRef } from 'e2e-utils'
+import { NextInstance } from 'test/lib/next-modes/base'
+import webdriver from 'next-webdriver'
+import { waitFor } from 'next-test-utils'
+
+describe('useSelectedLayoutSegment(s)', () => {
+ let next: NextInstance
+
+ beforeAll(async () => {
+ next = await createNext({
+ files: new FileRef(__dirname),
+ dependencies: {
+ react: 'latest',
+ 'react-dom': 'latest',
+ typescript: 'latest',
+ '@types/react': 'latest',
+ '@types/node': 'latest',
+ },
+ })
+ })
+ afterAll(() => next.destroy())
+
+ let browser: Awaited>
+ beforeEach(async () => {
+ browser = await webdriver(
+ next.url,
+ '/segment-name/value1/segment-name2/value2/value3/value4'
+ )
+ })
+
+ it('should return correct values for root layout', async () => {
+ expect(
+ await browser.elementByCss('#root > .segments').text()
+ ).toMatchInlineSnapshot(
+ `"[\\"segment-name\\",\\"value1\\",\\"segment-name2\\",\\"value2\\",\\"value3/value4\\"]"`
+ )
+
+ expect(
+ await browser.elementByCss('#root > .segment').text()
+ ).toMatchInlineSnapshot(`"\\"segment-name\\""`)
+ })
+
+ it('should return correct values in layout before static segment', async () => {
+ expect(
+ await browser.elementByCss('#before-static > .segments').text()
+ ).toMatchInlineSnapshot(
+ `"[\\"segment-name2\\",\\"value2\\",\\"value3/value4\\"]"`
+ )
+
+ expect(
+ await browser.elementByCss('#before-static > .segment').text()
+ ).toMatchInlineSnapshot(`"\\"segment-name2\\""`)
+ })
+
+ it('should return correct values in layout before param segment', async () => {
+ expect(
+ await browser.elementByCss('#before-param > .segments').text()
+ ).toMatchInlineSnapshot(`"[\\"value2\\",\\"value3/value4\\"]"`)
+
+ expect(
+ await browser.elementByCss('#before-param > .segment').text()
+ ).toMatchInlineSnapshot(`"\\"value2\\""`)
+ })
+
+ it('should return correct values in layout before catchall segment', async () => {
+ expect(
+ await browser.elementByCss('#before-catchall > .segments').text()
+ ).toMatchInlineSnapshot(`"[\\"value3/value4\\"]"`)
+
+ expect(
+ await browser.elementByCss('#before-catchall > .segment').text()
+ ).toMatchInlineSnapshot(`"\\"value3/value4\\""`)
+ })
+
+ it('should return correct values in layout after last segment', async () => {
+ expect(
+ await browser.elementByCss('#final > .segments').text()
+ ).toMatchInlineSnapshot(`"[]"`)
+
+ expect(
+ await browser.elementByCss('#final > .segment').text()
+ ).toMatchInlineSnapshot(`"null"`)
+ })
+
+ it('should correctly update when changing static segment', async () => {
+ browser.elementById('change-static').click()
+ await waitFor(100)
+
+ expect(
+ await browser.elementByCss('#root > .segments').text()
+ ).toMatchInlineSnapshot(
+ `"[\\"segment-name\\",\\"param1\\",\\"different-segment\\"]"`
+ )
+
+ expect(
+ await browser.elementByCss('#before-static > .segments').text()
+ ).toMatchInlineSnapshot(`"[\\"different-segment\\"]"`)
+
+ expect(
+ await browser.elementByCss('#before-static > .segment').text()
+ ).toMatchInlineSnapshot(`"\\"different-segment\\""`)
+ })
+
+ it('should correctly update when changing param segment', async () => {
+ browser.elementById('change-param').click()
+ await waitFor(100)
+
+ expect(
+ await browser.elementByCss('#root > .segments').text()
+ ).toMatchInlineSnapshot(
+ `"[\\"segment-name\\",\\"param1\\",\\"segment-name2\\",\\"different-value\\",\\"value3/value4'\\"]"`
+ )
+
+ expect(
+ await browser.elementByCss('#before-param > .segments').text()
+ ).toMatchInlineSnapshot(`"[\\"different-value\\",\\"value3/value4'\\"]"`)
+
+ expect(
+ await browser.elementByCss('#before-param > .segment').text()
+ ).toMatchInlineSnapshot(`"\\"different-value\\""`)
+ })
+
+ it('should correctly update when changing catchall segment', async () => {
+ browser.elementById('change-catchall').click()
+ await waitFor(100)
+
+ expect(
+ await browser.elementByCss('#root > .segments').text()
+ ).toMatchInlineSnapshot(
+ `"[\\"segment-name\\",\\"param1\\",\\"segment-name2\\",\\"value2\\",\\"different/random/paths'\\"]"`
+ )
+
+ expect(
+ await browser.elementByCss('#before-catchall > .segments').text()
+ ).toMatchInlineSnapshot(`"[\\"different/random/paths'\\"]"`)
+
+ expect(
+ await browser.elementByCss('#before-catchall > .segment').text()
+ ).toMatchInlineSnapshot(`"\\"different/random/paths'\\""`)
+ })
+})