Skip to content

Commit

Permalink
feat: support Next.JS version 14 (#29558)
Browse files Browse the repository at this point in the history
* feat: support Next.JS version 14 [run ci]

* bump circle cache [run ci]

* Update npm/webpack-dev-server/cypress/e2e/next.cy.ts

Co-authored-by: Matt Schile <[email protected]>

* Update cli/CHANGELOG.md

Co-authored-by: Matt Schile <[email protected]>

---------

Co-authored-by: Matt Schile <[email protected]>
  • Loading branch information
AtofStryker and mschile authored May 29, 2024
1 parent 2cf5cf8 commit cf6b29d
Show file tree
Hide file tree
Showing 35 changed files with 5,212 additions and 5,116 deletions.
2 changes: 1 addition & 1 deletion .circleci/cache-version.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Bump this version to force CI to re-create the cache from scratch.

05-09-24
05-23-24
10 changes: 5 additions & 5 deletions .circleci/workflows.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ mainBuildFilters: &mainBuildFilters
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
- 'update-v8-snapshot-cache-on-develop'
- 'publish-binary'
- 'feat/vite_5_support'
- 'feat/support_next_14'

# usually we don't build Mac app - it takes a long time
# but sometimes we want to really confirm we are doing the right thing
Expand All @@ -42,7 +42,7 @@ macWorkflowFilters: &darwin-workflow-filters
- equal: [ develop, << pipeline.git.branch >> ]
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
- equal: [ 'feat/vite_5_support', << pipeline.git.branch >> ]
- equal: [ 'feat/support_next_14', << pipeline.git.branch >> ]
- matches:
pattern: /^release\/\d+\.\d+\.\d+$/
value: << pipeline.git.branch >>
Expand All @@ -53,7 +53,7 @@ linuxArm64WorkflowFilters: &linux-arm64-workflow-filters
- equal: [ develop, << pipeline.git.branch >> ]
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
- equal: [ 'feat/vite_5_support', << pipeline.git.branch >> ]
- equal: [ 'feat/support_next_14', << pipeline.git.branch >> ]
- matches:
pattern: /^release\/\d+\.\d+\.\d+$/
value: << pipeline.git.branch >>
Expand All @@ -76,7 +76,7 @@ windowsWorkflowFilters: &windows-workflow-filters
- equal: [ develop, << pipeline.git.branch >> ]
# use the following branch as well to ensure that v8 snapshot cache updates are fully tested
- equal: [ 'update-v8-snapshot-cache-on-develop', << pipeline.git.branch >> ]
- equal: [ 'chore/fix_illegal_characters_in_windows', << pipeline.git.branch >> ]
- equal: [ 'feat/support_next_14', << pipeline.git.branch >> ]
- matches:
pattern: /^release\/\d+\.\d+\.\d+$/
value: << pipeline.git.branch >>
Expand Down Expand Up @@ -152,7 +152,7 @@ commands:
name: Set environment variable to determine whether or not to persist artifacts
command: |
echo "Setting SHOULD_PERSIST_ARTIFACTS variable"
echo 'if ! [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "feat/vite_5_support" ]]; then
echo 'if ! [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "feat/support_next_14" ]]; then
export SHOULD_PERSIST_ARTIFACTS=true
fi' >> "$BASH_ENV"
# You must run `setup_should_persist_artifacts` command and be using bash before running this command
Expand Down
8 changes: 6 additions & 2 deletions cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
<!-- See the ../guides/writing-the-cypress-changelog.md for details on writing the changelog. -->
## 13.10.1
## 13.11.0

_Released 5/28/2024 (PENDING)_
_Released 6/4/2024 (PENDING)_

**Features:**

- Added support for [Next.js 14](https://nextjs.org/blog/next-14) for component testing. Addresses [#28185](https://github.com/cypress-io/cypress/issues/28185).

**Bugfixes:**

Expand Down
100 changes: 98 additions & 2 deletions npm/webpack-dev-server/cypress/e2e/next.cy.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
/// <reference path="../support/e2e.ts" />
import type { ProjectFixtureDir } from '@tooling/system-tests/lib/fixtureDirs'

const WEBPACK_REACT: ProjectFixtureDir[] = ['next-12', 'next-12.1.6', 'next-13', 'next-13-tsconfig']

const WEBPACK_REACT: ProjectFixtureDir[] = ['next-12', 'next-12.1.6', 'next-13', 'next-13-tsconfig', 'next-14']
// Add to this list to focus on a particular permutation
const ONLY_PROJECTS: ProjectFixtureDir[] = []

Expand Down Expand Up @@ -106,3 +105,100 @@ for (const project of WEBPACK_REACT) {
})
})
}

// Since next-14-tsconfig-tailwind does not use the fixture directory we need to write our own test suite
// We want to specifically test typescript files with next-14 as there have been known problems with
// module: bundler and cypress compatibility
describe(`Working with next-14-tsconfig-tailwind`, () => {
beforeEach(() => {
cy.scaffoldProject('next-14-tsconfig-tailwind')
cy.openProject('next-14-tsconfig-tailwind', ['--component'])
cy.startAppServer('component')
})

it('should mount a passing test', () => {
cy.visitApp()
cy.specsPageIsVisible()
cy.contains('page.cy.tsx').click()
cy.waitForSpecToFinish({ passCount: 1 })
})

it('should live-reload on src changes', () => {
cy.visitApp()
cy.specsPageIsVisible()

cy.contains('page.cy.tsx').click()
cy.waitForSpecToFinish({ passCount: 1 })

cy.withCtx(async (ctx) => {
const indexPath = ctx.path.join('app', 'page.tsx')

await ctx.actions.file.writeFileInProject(
indexPath,
(await ctx.file.readFileInProject(indexPath)).replace('Welcome to', 'Hello from'),
)
})

cy.waitForSpecToFinish({ failCount: 1 })
cy.get('.test-err-code-frame').should('be.visible')

cy.withCtx(async (ctx) => {
const indexTestPath = ctx.path.join('app', 'page.cy.tsx')

await ctx.actions.file.writeFileInProject(
indexTestPath,
(await ctx.file.readFileInProject(indexTestPath)).replace('Welcome to', 'Hello from'),
)
})

cy.waitForSpecToFinish({ passCount: 1 })
})

it('should show compilation errors on src changes', () => {
cy.visitApp()
cy.specsPageIsVisible()

cy.contains('page.cy.tsx').click()
cy.waitForSpecToFinish({ passCount: 1 })

// Create compilation error
cy.withCtx(async (ctx) => {
const indexPath = ctx.path.join('app', 'page.tsx')

await ctx.actions.file.writeFileInProject(
indexPath,
(await ctx.file.readFileInProject(indexPath)).replace('export', 'expart'),
)
})

// The test should fail and the stack trace should appear in the command log
cy.waitForSpecToFinish({ failCount: 1 })
cy.contains('The following error originated from your test code, not from Cypress.').should('exist')
})

it('should detect new spec', { retries: 15 }, () => {
cy.visitApp()
cy.specsPageIsVisible()

cy.withCtx(async (ctx) => {
const newTestPath = ctx.path.join('app', 'New.cy.tsx')
const indexTestPath = ctx.path.join('app', 'page.cy.tsx')

await ctx.actions.file.writeFileInProject(
newTestPath,
await ctx.file.readFileInProject(indexTestPath),
)
})

cy.contains('New.cy.tsx').click()
cy.waitForSpecToFinish({ passCount: 1 })
})

// Make sure tailwind styles are appearing in the test.
it('should allow import of global styles in support file', { retries: 15 }, () => {
cy.visitApp()
cy.specsPageIsVisible()
cy.contains('page-styles.cy.tsx').click()
cy.waitForSpecToFinish({ passCount: 1 })
})
})
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ export function sourceWebpackDevServer (config: WebpackDevServerConfig, webpackM

throw new CypressWebpackDevServerError(
`Incompatible major versions of webpack and webpack-dev-server!
webpack-dev-server major version ${webpackDevServer.majorVersion} only works with major versions of webpack ${webpackMajorVersion} - saw webpack-dev-server version ${json.version}.
webpack-dev-server major version ${webpackDevServer.majorVersion} only works with major versions of webpack 5 - saw webpack-dev-server version ${json.version}.
If using webpack major version 4, please install webpack-dev-server version 4 to be used with @cypress/webpack-dev-server or upgrade to webpack 5.`,
)
}
Expand Down
10 changes: 5 additions & 5 deletions npm/webpack-dev-server/test/handlers/nextHandler.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ import { WebpackDevServerConfig } from '../../src/devServer'
import '../support'

const expectWatchOverrides = (webpackConfig: Configuration) => {
expect(webpackConfig.watchOptions?.ignored).to.contain('**/node_modules/!(@cypress/webpack-dev-server/dist/browser.js)**')
expect((webpackConfig.watchOptions?.ignored as RegExp)?.test('**/node_modules/!(@cypress/webpack-dev-server/dist/browser.js)**')).to.be.true
}

const expectPagesDir = (webpackConfig: Configuration, projectRoot: string) => {
const ReactLoadablePlugin: any = webpackConfig.plugins?.find((plugin) => plugin.constructor.name === 'ReactLoadablePlugin')

expect(ReactLoadablePlugin.pagesDir).eq(path.join(projectRoot, 'pages'))
expect(ReactLoadablePlugin.pagesOrAppDir).eq(path.join(projectRoot, 'pages'))
}

const expectWebpackSpan = (webpackConfig: Configuration) => {
Expand Down Expand Up @@ -54,8 +54,8 @@ describe('nextHandler', function () {
// can take a while since we install node_modules
this.timeout(1000 * 60)

it('sources from a next-12 project', async () => {
const projectRoot = await scaffoldMigrationProject('next-12')
it('sources from a next-14 project', async () => {
const projectRoot = await scaffoldMigrationProject('next-14')

process.chdir(projectRoot)

Expand All @@ -75,7 +75,7 @@ describe('nextHandler', function () {
})

it('throws if nodeVersion is set to bundled', async () => {
const projectRoot = await scaffoldMigrationProject('next-12')
const projectRoot = await scaffoldMigrationProject('next-14')

process.chdir(projectRoot)

Expand Down
4 changes: 2 additions & 2 deletions packages/app/cypress/e2e/runner/ct-framework-errors.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,12 +136,12 @@ describe('Next.js', {
numTestsKeptInMemory: 1,
}, () => {
beforeEach(() => {
cy.scaffoldProject('next-12')
cy.scaffoldProject('next-14')
})

it('error conditions', () => {
const verify = loadErrorSpec({
projectName: 'next-12',
projectName: 'next-14',
configFile: 'cypress.config.js',
filePath: 'cypress/Errors.cy.jsx',
failCount: 4,
Expand Down
4 changes: 2 additions & 2 deletions packages/launchpad/cypress/e2e/config-warning.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -258,8 +258,8 @@ describe('component testing dependency warnings', () => {
})

it('does not show warning for project that does not require bundler to be installed', () => {
cy.scaffoldProject('next-12')
cy.openProject('next-12', ['--component'])
cy.scaffoldProject('next-14')
cy.openProject('next-14', ['--component'])
cy.visitLaunchpad()
cy.skipWelcome()
cy.get('[data-cy="warning-alert"]').should('not.exist')
Expand Down
2 changes: 1 addition & 1 deletion packages/scaffold-config/src/dependencies.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export const WIZARD_DEPENDENCY_NEXT = {
package: 'next',
installer: 'next',
description: 'The React Framework for Production',
minVersion: '^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0',
minVersion: '^10.0.0 || ^11.0.0 || ^12.0.0 || ^13.0.0 || ^14.0.0',
} as const

export const WIZARD_DEPENDENCY_ANGULAR_CLI = {
Expand Down
2 changes: 1 addition & 1 deletion packages/scaffold-config/test/unit/detect.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ describe('detectFramework', () => {
expect(actual.bundler).to.eq('vite')
})

;['10.0.0', '11.0.0', '12.0.0'].forEach((v) => {
;['10.0.0', '11.0.0', '12.0.0', '13.0.0', '14.0.0'].forEach((v) => {
it(`Next.js v${v}`, async () => {
const projectPath = await scaffoldMigrationProject('nextjs-unconfigured')

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2408,7 +2408,7 @@ Your configFile threw an error from: cypress-webpack.config.ts
We stopped running your tests because your config file crashed.
CypressWebpackDevServerError: Incompatible major versions of webpack and webpack-dev-server!
webpack-dev-server major version 5 only works with major versions of webpack 4 - saw webpack-dev-server version 5.0.4.
webpack-dev-server major version 5 only works with major versions of webpack 5 - saw webpack-dev-server version 5.0.4.
If using webpack major version 4, please install webpack-dev-server version 4 to be used with @cypress/webpack-dev-server or upgrade to webpack 5.
[stack trace lines]
`
33 changes: 33 additions & 0 deletions system-tests/projects/next-14-tsconfig-tailwind/app/globals.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
--foreground-rgb: 0, 0, 0;
--background-start-rgb: 214, 219, 220;
--background-end-rgb: 255, 255, 255;
}

@media (prefers-color-scheme: dark) {
:root {
--foreground-rgb: 255, 255, 255;
--background-start-rgb: 0, 0, 0;
--background-end-rgb: 0, 0, 0;
}
}

body {
color: rgb(var(--foreground-rgb));
background: linear-gradient(
to bottom,
transparent,
rgb(var(--background-end-rgb))
)
rgb(var(--background-start-rgb));
}

@layer utilities {
.text-balance {
text-wrap: balance;
}
}
22 changes: 22 additions & 0 deletions system-tests/projects/next-14-tsconfig-tailwind/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
import './globals.css'

const inter = Inter({ subsets: ['latin'] })

export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}

export default function RootLayout ({
children,
}: Readonly<{
children: React.ReactNode
}>) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import React from 'react'
import Home from './page'

describe('<Home />', () => {
it('renders', () => {
cy.mount(<Home />)
cy.contains('h1', 'Welcome to Next.js!')

// verify tailwind classes are applied correctly via import from support file.
cy.get('main').should('have.css', 'background-color', 'rgb(245, 158, 11)')
})
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import React from 'react'
import Home from './page'

describe('<Home />', () => {
it('renders', () => {
cy.mount(<Home />)
cy.contains('h1', 'Welcome to Next.js!')
})
})
7 changes: 7 additions & 0 deletions system-tests/projects/next-14-tsconfig-tailwind/app/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export default function Home () {
return (
<main className="bg-amber-500">
<h1> Welcome to Next.js! </h1>
</main>
)
}
24 changes: 24 additions & 0 deletions system-tests/projects/next-14-tsconfig-tailwind/cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import path from 'path'
import { defineConfig } from 'cypress'

export default defineConfig({
component: {
devServer: {
framework: 'next',
bundler: 'webpack',
// Necessary due to cypress/react resolving from cypress/node_modules rather than the project root
webpackConfig: {
resolve: {
alias: {
'react': path.resolve(__dirname, './node_modules/react'),
'react-dom': path.resolve(__dirname, './node_modules/react-dom'),
},
},
},
},
fixturesFolder: false,
},
// These tests should run quickly / fail quickly,
// since we intentionally causing error states for testing
defaultCommandTimeout: 1000,
})
Loading

5 comments on commit cf6b29d

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on cf6b29d May 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux x64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/13.11.0/linux-x64/develop-cf6b29db229cc825f27fd78e7baeafaa16576f9a/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on cf6b29d May 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the linux arm64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/13.11.0/linux-arm64/develop-cf6b29db229cc825f27fd78e7baeafaa16576f9a/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on cf6b29d May 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin x64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/13.11.0/darwin-x64/develop-cf6b29db229cc825f27fd78e7baeafaa16576f9a/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on cf6b29d May 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the win32 x64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/13.11.0/win32-x64/develop-cf6b29db229cc825f27fd78e7baeafaa16576f9a/cypress.tgz

@cypress-bot
Copy link
Contributor

@cypress-bot cypress-bot bot commented on cf6b29d May 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Circle has built the darwin arm64 version of the Test Runner.

Learn more about this pre-release build at https://on.cypress.io/advanced-installation#Install-pre-release-version

Run this command to install the pre-release locally:

npm install https://cdn.cypress.io/beta/npm/13.11.0/darwin-arm64/develop-cf6b29db229cc825f27fd78e7baeafaa16576f9a/cypress.tgz

Please sign in to comment.