next.js/test/production/app-dir/build-output-tree-view/build-output-tree-view.test.ts
build-output-tree-view.test.ts108 lines3.3 KB
import { nextTestSetup } from 'e2e-utils'
import path from 'path'

describe('build-output-tree-view', () => {
  // TODO(NAR-423): Migrate to Cache Components.
  describe.skip('with mixed static and dynamic pages and app router routes', () => {
    const { next } = nextTestSetup({
      files: path.join(__dirname, 'fixtures/mixed'),
      skipStart: true,
      env: {
        __NEXT_PRIVATE_DETERMINISTIC_BUILD_OUTPUT: '1',
      },
    })

    beforeAll(() => next.build())

    it('should show info about prerendered and dynamic routes in a tree view', async () => {
      expect(getTreeView(next.cliOutput)).toMatchInlineSnapshot(`
       "Route (app)             Revalidate  Expire
       ┌ ○ /_not-found
       ├ ƒ /api
       ├ ○ /api/force-static
       ├ ○ /app-static
       ├ ○ /cache-life-custom         ≈7m     ≈2h
       ├ ○ /cache-life-hours           1h      1d
       ├ ƒ /dynamic
       ├   /ppr/[slug]                 1w     30d
       │ ├ ◐ /ppr/[slug]               1w     30d
       │ ├ ◐ /ppr/days                 1d      1w
       │ └ ◐ /ppr/weeks                1w     30d
       └ ○ /revalidate                15m      1y

       Route (pages)           Revalidate  Expire
       ┌ ƒ /api/hello
       ├ ● /gsp-revalidate             5m      1y
       ├ ƒ /gssp
       └ ○ /static

       ○  (Static)             prerendered as static content
       ●  (SSG)                prerendered as static HTML (uses generateStaticParams)
       ◐  (Partial Prerender)  prerendered as static HTML with dynamic server-streamed content
       ƒ  (Dynamic)            server-rendered on demand"
      `)
    })
  })

  describe('with only a few static routes', () => {
    const { next } = nextTestSetup({
      files: path.join(__dirname, 'fixtures/minimal-static'),
      skipStart: true,
      env: {
        __NEXT_PRIVATE_DETERMINISTIC_BUILD_OUTPUT: '1',
      },
    })

    beforeAll(() => next.build())

    it('should show info about prerendered routes in a compact tree view', async () => {
      expect(getTreeView(next.cliOutput)).toMatchInlineSnapshot(`
       "Route (app)
       ┌ ○ /
       └ ○ /_not-found

       Route (pages)
       ─ ○ /static

       ○  (Static)  prerendered as static content"
      `)
    })
  })

  describe('with generated app routes that mix static and partial outputs', () => {
    const { next } = nextTestSetup({
      files: path.join(__dirname, '../../../e2e/app-dir/cache-components'),
      skipStart: true,
      env: {
        __NEXT_PRIVATE_DETERMINISTIC_BUILD_OUTPUT: '1',
      },
    })

    beforeAll(() => next.build())

    it('should show child route symbols for generated app paths', async () => {
      expect(getTreeView(next.cliOutput)).toContain(
        `├   /params/semantics/[lowcard]/[highcard]/layout-has/server
│ ├ ◐ /params/semantics/[lowcard]/[highcard]/layout-has/server
│ ├ ◐ /params/semantics/one/[highcard]/layout-has/server
│ └ ○ /params/semantics/one/build/layout-has/server`
      )
    })
  })
})

function getTreeView(cliOutput: string): string {
  let foundStart = false
  const lines: string[] = []

  for (const line of cliOutput.split('\n')) {
    foundStart ||= line.startsWith('Route ')

    if (foundStart) {
      lines.push(line)
    }
  }

  return lines.join('\n').trim()
}
Quest for Codev2.0.0
/
SIGN IN