diff --git a/test/integration/react-18/test/basics.js b/test/integration/react-18/test/basics.js
deleted file mode 100644
index 601ccef626349..0000000000000
--- a/test/integration/react-18/test/basics.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/* eslint-env jest */
-
-import webdriver from 'next-webdriver'
-import cheerio from 'cheerio'
-import { renderViaHTTP } from 'next-test-utils'
-
-export default (context, env) => {
- it('should only render once in SSR', async () => {
- await renderViaHTTP(context.appPort, '/')
- expect([...context.stdout.matchAll(/__render__/g)].length).toBe(1)
- })
-
- it('no warnings for image related link props', async () => {
- await renderViaHTTP(context.appPort, '/')
- expect(context.stderr).not.toContain('Warning: Invalid DOM property')
- expect(context.stderr).not.toContain('Warning: React does not recognize')
- })
-
- it('hydrates correctly for normal page', async () => {
- const browser = await webdriver(context.appPort, '/')
- expect(await browser.eval('window.didHydrate')).toBe(true)
- expect(await browser.elementById('react-dom-version').text()).toMatch(/18/)
- })
-
- it('useId() values should match on hydration', async () => {
- const html = await renderViaHTTP(context.appPort, '/use-id')
- const $ = cheerio.load(html)
- const ssrId = $('#id').text()
-
- const browser = await webdriver(context.appPort, '/use-id')
- const csrId = await browser.eval('document.getElementById("id").innerText')
-
- expect(ssrId).toEqual(csrId)
- })
-
- it('should contain dynamicIds in next data for dynamic imports', async () => {
- async function expectToContainPreload(page) {
- const html = await renderViaHTTP(context.appPort, `/${page}`)
- const $ = cheerio.load(html)
- const { dynamicIds } = JSON.parse($('#__NEXT_DATA__').html())
-
- if (env === 'dev') {
- expect(
- dynamicIds.find((id) =>
- id.includes(`pages/${page}.js -> ../components/foo`)
- )
- ).toBeTruthy()
- } else {
- expect(dynamicIds.length).toBe(1)
- }
- }
- await expectToContainPreload('dynamic')
- await expectToContainPreload('dynamic-suspense')
- })
-}
diff --git a/test/integration/react-18/test/concurrent.js b/test/integration/react-18/test/concurrent.js
deleted file mode 100644
index 04156020a4cdc..0000000000000
--- a/test/integration/react-18/test/concurrent.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/* eslint-env jest */
-
-import webdriver from 'next-webdriver'
-import { check, renderViaHTTP } from 'next-test-utils'
-
-export default (context, _render) => {
- async function withBrowser(path, cb) {
- let browser
- try {
- browser = await webdriver(context.appPort, path)
- await cb(browser)
- } finally {
- if (browser) {
- await browser.close()
- }
- }
- }
-
- it('flushes styled-jsx styles as the page renders', async () => {
- const html = await renderViaHTTP(
- context.appPort,
- '/use-flush-effect/styled-jsx'
- )
- const stylesOccurrence = html.match(/color:(\s)*(?:blue|#00f)/g) || []
- expect(stylesOccurrence.length).toBe(1)
-
- await withBrowser('/use-flush-effect/styled-jsx', async (browser) => {
- await check(
- () => browser.waitForElementByCss('#__jsx-900f996af369fc74').text(),
- /(?:blue|#00f)/
- )
- await check(
- () => browser.waitForElementByCss('#__jsx-8b0811664c4e575e').text(),
- /red/
- )
- })
- })
-}
diff --git a/test/integration/react-18/test/index.test.js b/test/integration/react-18/test/index.test.js
deleted file mode 100644
index da32192bc02c5..0000000000000
--- a/test/integration/react-18/test/index.test.js
+++ /dev/null
@@ -1,50 +0,0 @@
-/* eslint-env jest */
-
-import { join } from 'path'
-
-import { File, renderViaHTTP, runDevSuite, runProdSuite } from 'next-test-utils'
-import concurrent from './concurrent'
-import basics from './basics'
-import strictMode from './strict-mode'
-
-const appDir = join(__dirname, '../app')
-const indexPage = new File(join(appDir, 'pages/index.js'))
-
-describe('Basics', () => {
- runTests('default setting with react 18', basics)
-})
-
-function runTestsAgainstRuntime(runtime) {
- runTests(
- `Concurrent mode in the ${runtime} runtime`,
- (context, env) => {
- concurrent(context, (p, q) => renderViaHTTP(context.appPort, p, q))
- strictMode(context)
-
- it('should not have invalid config warning', async () => {
- await renderViaHTTP(context.appPort, '/')
- expect(context.stderr).not.toContain('not exist in this version')
- })
- },
- {
- beforeAll: (env) => {
- indexPage.replace(
- "// runtime: 'experimental-edge'",
- `runtime: '${runtime}'`
- )
- },
- afterAll: (env) => {
- indexPage.restore()
- },
- }
- )
-}
-
-runTestsAgainstRuntime('experimental-edge')
-runTestsAgainstRuntime('nodejs')
-
-function runTests(name, fn, opts) {
- const suiteOptions = { ...opts, runTests: fn }
- runDevSuite(name, appDir, suiteOptions)
- runProdSuite(name, appDir, suiteOptions)
-}
diff --git a/test/integration/react-18/test/strict-mode.js b/test/integration/react-18/test/strict-mode.js
deleted file mode 100644
index fc305ec469fdc..0000000000000
--- a/test/integration/react-18/test/strict-mode.js
+++ /dev/null
@@ -1,16 +0,0 @@
-/* eslint-env jest */
-
-import webdriver from 'next-webdriver'
-
-export default (context) => {
- describe('', () => {
- it('should not have the initial route announced', async () => {
- const browser = await webdriver(context.appPort, '/')
- const title = await browser
- .waitForElementByCss('#__next-route-announcer__')
- .text()
-
- expect(title).toBe('')
- })
- })
-}
diff --git a/test/integration/react-18/app/components/foo.js b/test/integration/react-current-version/app/components/foo.js
similarity index 100%
rename from test/integration/react-18/app/components/foo.js
rename to test/integration/react-current-version/app/components/foo.js
diff --git a/test/integration/react-18/app/components/red.tsx b/test/integration/react-current-version/app/components/red.tsx
similarity index 85%
rename from test/integration/react-18/app/components/red.tsx
rename to test/integration/react-current-version/app/components/red.tsx
index 3da9eaccfef4b..1ea444aa515d2 100644
--- a/test/integration/react-18/app/components/red.tsx
+++ b/test/integration/react-current-version/app/components/red.tsx
@@ -1,5 +1,5 @@
import React, { Suspense } from 'react'
-import { createStreamingData } from '../../test/streaming-data'
+import { createStreamingData } from './streaming-data'
const Data = createStreamingData()
diff --git a/test/integration/react-18/test/streaming-data.js b/test/integration/react-current-version/app/components/streaming-data.js
similarity index 100%
rename from test/integration/react-18/test/streaming-data.js
rename to test/integration/react-current-version/app/components/streaming-data.js
diff --git a/test/integration/react-18/app/next.config.js b/test/integration/react-current-version/app/next.config.js
similarity index 100%
rename from test/integration/react-18/app/next.config.js
rename to test/integration/react-current-version/app/next.config.js
diff --git a/test/integration/react-18/app/package.json b/test/integration/react-current-version/app/package.json
similarity index 100%
rename from test/integration/react-18/app/package.json
rename to test/integration/react-current-version/app/package.json
diff --git a/test/integration/react-18/app/pages/dynamic-suspense.js b/test/integration/react-current-version/app/pages/dynamic-suspense.js
similarity index 100%
rename from test/integration/react-18/app/pages/dynamic-suspense.js
rename to test/integration/react-current-version/app/pages/dynamic-suspense.js
diff --git a/test/integration/react-18/app/pages/dynamic.js b/test/integration/react-current-version/app/pages/dynamic.js
similarity index 100%
rename from test/integration/react-18/app/pages/dynamic.js
rename to test/integration/react-current-version/app/pages/dynamic.js
diff --git a/test/integration/react-18/app/pages/index.js b/test/integration/react-current-version/app/pages/index.js
similarity index 100%
rename from test/integration/react-18/app/pages/index.js
rename to test/integration/react-current-version/app/pages/index.js
diff --git a/test/integration/react-18/app/pages/use-flush-effect/styled-jsx.tsx b/test/integration/react-current-version/app/pages/use-flush-effect/styled-jsx.tsx
similarity index 100%
rename from test/integration/react-18/app/pages/use-flush-effect/styled-jsx.tsx
rename to test/integration/react-current-version/app/pages/use-flush-effect/styled-jsx.tsx
diff --git a/test/integration/react-18/app/pages/use-id.js b/test/integration/react-current-version/app/pages/use-id.js
similarity index 100%
rename from test/integration/react-18/app/pages/use-id.js
rename to test/integration/react-current-version/app/pages/use-id.js
diff --git a/test/integration/react-18/app/tsconfig.json b/test/integration/react-current-version/app/tsconfig.json
similarity index 100%
rename from test/integration/react-18/app/tsconfig.json
rename to test/integration/react-current-version/app/tsconfig.json
diff --git a/test/integration/react-current-version/test/index.test.js b/test/integration/react-current-version/test/index.test.js
new file mode 100644
index 0000000000000..77c59c103a3b3
--- /dev/null
+++ b/test/integration/react-current-version/test/index.test.js
@@ -0,0 +1,147 @@
+/* eslint-env jest */
+
+import { join } from 'path'
+
+import cheerio from 'cheerio'
+import {
+ check,
+ File,
+ renderViaHTTP,
+ runDevSuite,
+ runProdSuite,
+} from 'next-test-utils'
+import webdriver from 'next-webdriver'
+
+const appDir = join(__dirname, '../app')
+const indexPage = new File(join(appDir, 'pages/index.js'))
+
+describe('Basics', () => {
+ runTests('default setting', (context, env) => {
+ it('should only render once in SSR', async () => {
+ await renderViaHTTP(context.appPort, '/')
+ expect([...context.stdout.matchAll(/__render__/g)].length).toBe(1)
+ })
+
+ it('no warnings for image related link props', async () => {
+ await renderViaHTTP(context.appPort, '/')
+ expect(context.stderr).not.toContain('Warning: Invalid DOM property')
+ expect(context.stderr).not.toContain('Warning: React does not recognize')
+ })
+
+ it('hydrates correctly for normal page', async () => {
+ const browser = await webdriver(context.appPort, '/')
+ expect(await browser.eval('window.didHydrate')).toBe(true)
+ expect(await browser.elementById('react-dom-version').text()).toMatch(
+ /18/
+ )
+ })
+
+ it('useId() values should match on hydration', async () => {
+ const html = await renderViaHTTP(context.appPort, '/use-id')
+ const $ = cheerio.load(html)
+ const ssrId = $('#id').text()
+
+ const browser = await webdriver(context.appPort, '/use-id')
+ const csrId = await browser.eval(
+ 'document.getElementById("id").innerText'
+ )
+
+ expect(ssrId).toEqual(csrId)
+ })
+
+ it('should contain dynamicIds in next data for dynamic imports', async () => {
+ async function expectToContainPreload(page) {
+ const html = await renderViaHTTP(context.appPort, `/${page}`)
+ const $ = cheerio.load(html)
+ const { dynamicIds } = JSON.parse($('#__NEXT_DATA__').html())
+
+ if (env === 'dev') {
+ expect(
+ dynamicIds.find((id) =>
+ id.includes(`pages/${page}.js -> ../components/foo`)
+ )
+ ).toBeTruthy()
+ } else {
+ expect(dynamicIds.length).toBe(1)
+ }
+ }
+ await expectToContainPreload('dynamic')
+ await expectToContainPreload('dynamic-suspense')
+ })
+ })
+})
+
+function runTestsAgainstRuntime(runtime) {
+ runTests(
+ `Concurrent mode in the ${runtime} runtime`,
+ (context, env) => {
+ async function withBrowser(path, cb) {
+ let browser
+ try {
+ browser = await webdriver(context.appPort, path)
+ await cb(browser)
+ } finally {
+ if (browser) {
+ await browser.close()
+ }
+ }
+ }
+
+ it('flushes styled-jsx styles as the page renders', async () => {
+ const html = await renderViaHTTP(
+ context.appPort,
+ '/use-flush-effect/styled-jsx'
+ )
+ const stylesOccurrence = html.match(/color:(\s)*(?:blue|#00f)/g) || []
+ expect(stylesOccurrence.length).toBe(1)
+
+ await withBrowser('/use-flush-effect/styled-jsx', async (browser) => {
+ await check(
+ () => browser.waitForElementByCss('#__jsx-900f996af369fc74').text(),
+ /(?:blue|#00f)/
+ )
+ await check(
+ () => browser.waitForElementByCss('#__jsx-8b0811664c4e575e').text(),
+ /red/
+ )
+ })
+ })
+
+ describe('', () => {
+ it('should not have the initial route announced', async () => {
+ const browser = await webdriver(context.appPort, '/')
+ const title = await browser
+ .waitForElementByCss('#__next-route-announcer__')
+ .text()
+
+ expect(title).toBe('')
+ })
+ })
+
+ it('should not have invalid config warning', async () => {
+ await renderViaHTTP(context.appPort, '/')
+ expect(context.stderr).not.toContain('not exist in this version')
+ })
+ },
+ {
+ beforeAll: (env) => {
+ indexPage.replace(
+ "// runtime: 'experimental-edge'",
+ `runtime: '${runtime}'`
+ )
+ },
+ afterAll: (env) => {
+ indexPage.restore()
+ },
+ }
+ )
+}
+
+runTestsAgainstRuntime('experimental-edge')
+runTestsAgainstRuntime('nodejs')
+
+function runTests(name, fn, opts) {
+ const suiteOptions = { ...opts, runTests: fn }
+ runDevSuite(name, appDir, suiteOptions)
+ runProdSuite(name, appDir, suiteOptions)
+}
diff --git a/test/integration/react-current-version/tsconfig.json b/test/integration/react-current-version/tsconfig.json
new file mode 100644
index 0000000000000..1d4f624eff7d9
--- /dev/null
+++ b/test/integration/react-current-version/tsconfig.json
@@ -0,0 +1,24 @@
+{
+ "compilerOptions": {
+ "target": "ES2017",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "skipLibCheck": true,
+ "strict": false,
+ "noEmit": true,
+ "incremental": true,
+ "module": "esnext",
+ "esModuleInterop": true,
+ "moduleResolution": "node",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ]
+ },
+ "include": ["next-env.d.ts", ".next/types/**/*.ts", "**/*.ts", "**/*.tsx"],
+ "exclude": ["node_modules"]
+}