Repository: vercel/next.js
Pull request: [test] isolate parallel metadata test

### What

Isolate parallel-routes related test cases for streaming metadata into a standalone test suite. Prepared to add more parallel route test cases into it.

Changed files:
filename: test/e2e/app-dir/metadata-streaming-parallel-routes/app/layout.tsx
patch: @@ -0,0 +1,22 @@
+import Link from 'next/link'
+import { ReactNode } from 'react'
+
+export default function Root({ children }: { children: ReactNode }) {
+  return (
+    <html>
+      <body>
+        <div>
+          <Link href="/parallel-routes" id="to-parallel-routes">
+            {`to /parallel-routes`}
+          </Link>
+          <br />
+          <Link href="/parallel-routes-default" id="to-default">
+            {`to /parallel-routes-default`}
+          </Link>
+          <br />
+        </div>
+        {children}
+      </body>
+    </html>
+  )
+}

filename: test/e2e/app-dir/metadata-streaming-parallel-routes/app/page.tsx
patch: @@ -0,0 +1,12 @@
+export default function Page() {
+  return <p>index page</p>
+}
+
+export async function generateMetadata() {
+  await new Promise((resolve) => setTimeout(resolve, 1 * 1000))
+  return {
+    title: 'index page',
+  }
+}
+
+export const dynamic = 'force-dynamic'

filename: test/e2e/app-dir/metadata-streaming-parallel-routes/metadata-streaming-parallel-routes.test.ts
patch: @@ -0,0 +1,60 @@
+import { nextTestSetup } from 'e2e-utils'
+import { retry } from 'next-test-utils'
+
+describe('app-dir - metadata-streaming', () => {
+  const { next } = nextTestSetup({
+    files: __dirname,
+  })
+
+  it('should only insert metadata once for parallel routes when slots match', async () => {
+    const browser = await next.browser('/parallel-routes')
+
+    expect((await browser.elementsByCss('head title')).length).toBe(1)
+    expect((await browser.elementsByCss('body title')).length).toBe(0)
+    expect(await browser.elementByCss('title').text()).toBe('parallel title')
+
+    const $ = await next.render$('/parallel-routes')
+    expect($('title').length).toBe(1)
+    expect($('head title').text()).toBe('parallel title')
+
+    // validate behavior remains the same on client navigations
+    await browser.elementByCss('[href="/parallel-routes/test-page"]').click()
+
+    await retry(async () => {
+      expect(await browser.elementByCss('title').text()).toContain(
+        'Dynamic api'
+      )
+    })
+
+    expect((await browser.elementsByCss('title')).length).toBe(1)
+  })
+
+  it('should only insert metadata once for parallel routes when there is a missing slot', async () => {
+    const browser = await next.browser('/parallel-routes')
+    await browser.elementByCss('[href="/parallel-routes/no-bar"]').click()
+
+    // Wait for navigation is finished and metadata is updated
+    await retry(async () => {
+      expect(await browser.elementByCss('title').text()).toContain(
+        'Dynamic api'
+      )
+    })
+
+    await retry(async () => {
+      expect((await browser.elementsByCss('title')).length).toBe(1)
+    })
+  })
+
+  it('should still render metadata if children is not rendered in parallel routes layout', async () => {
+    const browser = await next.browser('/parallel-routes-default')
+
+    expect((await browser.elementsByCss('title')).length).toBe(1)
+    expect(await browser.elementByCss('body title').text()).toBe(
+      'parallel-routes-default layout title'
+    )
+
+    const $ = await next.render$('/parallel-routes-default')
+    expect($('title').length).toBe(1)
+    expect($('body title').text()).toBe('parallel-routes-default layout title')
+  })
+})

filename: test/e2e/app-dir/metadata-streaming-parallel-routes/next.config.js
patch: @@ -0,0 +1,6 @@
+/**
+ * @type {import('next').NextConfig}
+ */
+const nextConfig = {}
+
+module.exports = nextConfig

filename: test/e2e/app-dir/metadata-streaming/metadata-streaming.test.ts
patch: @@ -88,58 +88,6 @@ describe('app-dir - metadata-streaming', () => {
     expect((await browser.elementsByCss('body meta')).length).toBe(9)
   })
 
-  it('should only insert metadata once for parallel routes when slots match', async () => {
-    const browser = await next.browser('/parallel-routes')
-
-    expect((await browser.elementsByCss('head title')).length).toBe(1)
-    expect((await browser.elementsByCss('body title')).length).toBe(0)
-    expect(await browser.elementByCss('title').text()).toBe('parallel title')
-
-    const $ = await next.render$('/parallel-routes')
-    expect($('title').length).toBe(1)
-    expect($('head title').text()).toBe('parallel title')
-
-    // validate behavior remains the same on client navigations
-    await browser.elementByCss('[href="/parallel-routes/test-page"]').click()
-
-    await retry(async () => {
-      expect(await browser.elementByCss('title').text()).toContain(
-        'Dynamic api'
-      )
-    })
-
-    expect((await browser.elementsByCss('title')).length).toBe(1)
-  })
-
-  it('should only insert metadata once for parallel routes when there is a missing slot', async () => {
-    const browser = await next.browser('/parallel-routes')
-    await browser.elementByCss('[href="/parallel-routes/no-bar"]').click()
-
-    // Wait for navigation is finished and metadata is updated
-    await retry(async () => {
-      expect(await browser.elementByCss('title').text()).toContain(
-        'Dynamic api'
-      )
-    })
-
-    await retry(async () => {
-      expect((await browser.elementsByCss('title')).length).toBe(1)
-    })
-  })
-
-  it('should still render metadata if children is not rendered in parallel routes layout', async () => {
-    const browser = await next.browser('/parallel-routes-default')
-
-    expect((await browser.elementsByCss('title')).length).toBe(1)
-    expect(await browser.elementByCss('body title').text()).toBe(
-      'parallel-routes-default layout title'
-    )
-
-    const $ = await next.render$('/parallel-routes-default')
-    expect($('title').length).toBe(1)
-    expect($('body title').text()).toBe('parallel-routes-default layout title')
-  })
-
   describe('dynamic api', () => {
     it('should render metadata to body', async () => {
       const $ = await next.render$('/dynamic-api')