Repository: vercel/next.js
Pull request: [test] Improve deployment skew test for Pages Router data routes

Actually test the behavior by switching between two builds, as opposed to selectively blocking some routes.

Changed files:
filename: test/integration/ssg-data-404/next.config.js
patch: @@ -0,0 +1,8 @@
+/**
+ * @type {import('next').NextConfig}
+ */
+const nextConfig = {
+  distDir: process.env.DIST_DIR && '.next.' + process.env.DIST_DIR,
+}
+
+module.exports = nextConfig

filename: test/integration/ssg-data-404/test/index.test.ts
patch: @@ -14,29 +14,35 @@ import {
 
 const appDir = join(__dirname, '..')
 
-let app
-let appPort
-let proxyServer
 let proxyPort
-let should404Data = false
 
-const runTests = () => {
-  it('should hard navigate when a new deployment occurs', async () => {
+const runTests = (switchDeployment: (bool) => void) => {
+  it('index to gsp', async () => {
+    switchDeployment(false)
     const browser = await webdriver(proxyPort, '/')
 
     await browser.eval('window.beforeNav = 1')
-    expect(await browser.elementByCss('#index').text()).toBe('Index page')
+    await browser.waitForElementByCss('#index')
 
-    should404Data = true
+    switchDeployment(true)
 
     await browser.eval(`(function() {
       window.next.router.push('/gsp')
     })()`)
     await browser.waitForElementByCss('#gsp')
 
     expect(await browser.eval('window.beforeNav')).toBeFalsy()
+  })
+
+  it('gsp to gssp', async () => {
+    switchDeployment(false)
+    const browser = await webdriver(proxyPort, '/gsp')
 
     await browser.eval('window.beforeNav = 1')
+    await browser.waitForElementByCss('#gsp')
+
+    switchDeployment(true)
+
     await browser.eval(`(function() {
       window.next.router.push('/gssp')
     })()`)
@@ -46,61 +52,108 @@ const runTests = () => {
   })
 }
 
-describe('SSG data 404', () => {
+describe('SSG data 404 - hard navigate when a new deployment occurs', () => {
   if (process.platform === 'win32') {
     it('should skip this suite on Windows', () => {})
     return
   }
 
-  ;(process.env.TURBOPACK_BUILD ? describe.skip : describe)(
-    'development mode',
-    () => {
-      beforeAll(async () => {
-        appPort = await findPort()
-        app = await launchApp(appDir, appPort)
+  describe('development mode', () => {
+    let should404Data = false
+    let apps = []
+    let proxyServer
 
-        const proxy = httpProxy.createProxyServer({
-          target: `http://localhost:${appPort}`,
-        })
-        proxyPort = await findPort()
+    beforeAll(async () => {
+      const appPort = await findPort()
+      apps.push(await launchApp(appDir, appPort))
 
-        proxyServer = http.createServer((req, res) => {
-          req.on('error', (e) => {
-            require('console').error(e)
-          })
-          res.on('error', (e) => {
-            require('console').error(e)
-          })
-          if (should404Data && req.url.match(/\/_next\/data/)) {
-            res.statusCode = 404
-            return res.end('not found')
-          }
-          proxy.web(req, res)
-        })
+      const proxy = httpProxy.createProxyServer({
+        target: `http://localhost:${appPort}`,
+      })
+      proxyPort = await findPort()
 
-        await new Promise<void>((resolve) => {
-          proxyServer.listen(proxyPort, () => resolve())
+      proxyServer = http.createServer((req, res) => {
+        req.on('error', (e) => {
+          require('console').error(e)
         })
+        res.on('error', (e) => {
+          require('console').error(e)
+        })
+        if (should404Data && req.url.match(/\/_next\/data/)) {
+          res.statusCode = 404
+          return res.end('not found')
+        }
+        proxy.web(req, res)
       })
-      afterAll(async () => {
-        await killApp(app)
-        proxyServer.close()
+
+      await new Promise<void>((resolve) => {
+        proxyServer.listen(proxyPort, () => resolve())
       })
+    })
+    afterAll(async () => {
+      for (const app of apps) {
+        await killApp(app)
+      }
+      proxyServer.close()
+    })
+
+    runTests((v) => {
+      should404Data = v
+    })
+  })
+
+  describe.each([
+    { name: 'with build id' },
+    {
+      name: 'with deployment id',
+      NEXT_DEPLOYMENT_ID1: 'deployment-id-1',
+      NEXT_DEPLOYMENT_ID2: 'deployment-id-2',
+    },
+  ])(
+    'production mode $name',
+    ({ NEXT_DEPLOYMENT_ID1, NEXT_DEPLOYMENT_ID2 }) => {
+      let shouldSwitchDeployment = false
+      let apps = []
+      let proxyServer
 
-      runTests()
-    }
-  )
-  ;(process.env.TURBOPACK_DEV ? describe.skip : describe)(
-    'production mode',
-    () => {
       beforeAll(async () => {
-        await nextBuild(appDir)
+        await nextBuild(appDir, [], {
+          env: {
+            DIST_DIR: '1',
+            NEXT_DEPLOYMENT_ID: NEXT_DEPLOYMENT_ID1,
+          },
+        })
+        let appPort1 = await findPort()
+        apps.push(
+          await nextStart(appDir, appPort1, {
+            env: {
+              DIST_DIR: '1',
+              NEXT_DEPLOYMENT_ID: NEXT_DEPLOYMENT_ID1,
+            },
+          })
+        )
 
-        appPort = await findPort()
-        app = await nextStart(appDir, appPort)
+        await nextBuild(appDir, [], {
+          env: {
+            DIST_DIR: '2',
+            NEXT_DEPLOYMENT_ID: NEXT_DEPLOYMENT_ID2,
+          },
+        })
+        let appPort2 = await findPort()
+        apps.push(
+          await nextStart(appDir, appPort2, {
+            env: {
+              DIST_DIR: '2',
+              NEXT_DEPLOYMENT_ID: NEXT_DEPLOYMENT_ID2,
+            },
+          })
+        )
 
-        const proxy = httpProxy.createProxyServer({
-          target: `http://localhost:${appPort}`,
+        const proxy1 = httpProxy.createProxyServer({
+          target: `http://localhost:${appPort1}`,
+        })
+        const proxy2 = httpProxy.createProxyServer({
+          target: `http://localhost:${appPort2}`,
         })
         proxyPort = await findPort()
 
@@ -111,11 +164,15 @@ describe('SSG data 404', () => {
           res.on('error', (e) => {
             require('console').error(e)
           })
-          if (should404Data && req.url.match(/\/_next\/data/)) {
-            res.statusCode = 404
-            return res.end('not found')
+
+          if (shouldSwitchDeployment) {
+            proxy2.web(req, res, undefined, (e) => {
+              require('console').error(e)
+            })
+            return
           }
-          proxy.web(req, res, undefined, (e) => {
+
+          proxy1.web(req, res, undefined, (e) => {
             require('console').error(e)
           })
         })
@@ -125,11 +182,15 @@ describe('SSG data 404', () => {
         })
       })
       afterAll(async () => {
-        await killApp(app)
+        for (const app of apps) {
+          await killApp(app)
+        }
         proxyServer.close()
       })
 
-      runTests()
+      runTests((v) => {
+        shouldSwitchDeployment = v
+      })
     }
   )
 })