Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/src/pipeline/@pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,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" != "chore/remove_unused_anchors" ]]; then
echo 'if ! [[ "$CIRCLE_BRANCH" != "develop" && "$CIRCLE_BRANCH" != "release/"* && "$CIRCLE_BRANCH" != "feat/support_next_16" ]]; 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
2 changes: 1 addition & 1 deletion .circleci/src/pipeline/workflows/@main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ linux-x64:
- 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/remove_unused_anchors', << pipeline.git.branch >> ]
- equal: [ 'feat/support_next_16', << pipeline.git.branch >> ]
- matches:
pattern: /^release\/\d+\.\d+\.\d+$/
value: << pipeline.git.branch >>
Expand Down
8 changes: 6 additions & 2 deletions cli/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
<!-- See the ../guides/writing-the-cypress-changelog.md for details on writing the changelog. -->
## 15.6.1
## 15.7.0

_Released 11/18/2025 (PENDING)_

**Performance:**

- Limits the number of matched elements that are tested for visibility when added to a command log entry. Fixes a crash scenario related to rapid successive DOM additions in conjunction with a large number of elements returned from a query. Addressed in [#32937](https://github.com/cypress-io/cypress/pull/32937).

**Features:**

- `Next.js` version 16 is now supported within component testing. Currently, `webpack` is used to bundle Next.js components. Turbopack, the [new default](https://nextjs.org/docs/app/guides/upgrading/version-16#turbopack-by-default) inside Next.js 16, is not yet supported within Cypress. Addresses [#32857](https://github.com/cypress-io/cypress/issues/32857).

**Bugfixes:**

- Fixed an issue where [`cy.wrap()`](https://docs.cypress.io/api/commands/wrap) would cause infinite recursion and freeze the Cypress App when called with objects containing circular references. Fixes [#24715](https://github.com/cypress-io/cypress/issues/24715). Addressed in [#32917](https://github.com/cypress-io/cypress/pull/32917).
Expand All @@ -24,7 +28,7 @@ _Released 11/4/2025_

**Features:**

- Added a 'Self-healed' badge to the Command Log when [`cy.prompt()`](https://docs.cypress.io/api/commands/prompt) steps automatically recover after the element they need is not found in the cache. Addressed in [#32802](https://github.com/cypress-io/cypress/pull/32802).
- Added a 'Self-healed' badge to the Command Log when [`cy.prompt()`](https://docs.cypress.io/api/commands/prompt) steps automatically recover after the element they need is not found in the cache. Addressed in [#32802](https://github.com/cypress-io/cypress/pull/32802).
- [`cy.prompt()`](https://docs.cypress.io/api/commands/prompt) will now show a warning in the `Get code` modal when there are unsaved changes in `Studio` that will be lost if the user saves the generated code. Addressed in [#32741](https://github.com/cypress-io/cypress/pull/32741).

**Bugfixes:**
Expand Down
8 changes: 5 additions & 3 deletions npm/webpack-dev-server/cypress/e2e/next.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@ for (const project of NEXT_PROJECTS) {
})
}

const NEXT_PROJECTS_TSCONFIG_TAILWIND: ProjectFixtureDir[] = ['next-14-tsconfig-tailwind', 'next-15-tsconfig-tailwind']
const NEXT_PROJECTS_TSCONFIG_TAILWIND: ProjectFixtureDir[] = ['next-14-tsconfig-tailwind', 'next-15-tsconfig-tailwind', 'next-16-tsconfig-tailwind']

for (const project of NEXT_PROJECTS_TSCONFIG_TAILWIND) {
// Since next-tsconfig-tailwind does not use the fixture directory we need to write our own test suite
Expand Down Expand Up @@ -143,9 +143,11 @@ for (const project of NEXT_PROJECTS_TSCONFIG_TAILWIND) {
})

cy.waitForSpecToFinish({ failCount: 1 })
if (project !== 'next-15-tsconfig-tailwind') {
// code frames not fully working with next 15
if (project !== 'next-15-tsconfig-tailwind' && project !== 'next-16-tsconfig-tailwind') {
// code frames not fully working with next 15/16
cy.get('.test-err-code-frame').should('be.visible')
} else {
cy.get('.runnable-err-message').should('be.visible')
}

cy.withCtx(async (ctx) => {
Expand Down
145 changes: 31 additions & 114 deletions npm/webpack-dev-server/src/helpers/nextHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import Module from 'module'
import type { Configuration } from 'webpack'
import * as fs from 'fs'
import * as path from 'path'
import semver from 'semver'
import type { PresetHandlerResult, WebpackDevServerConfig } from '../devServer'
import { cypressWebpackPath, getMajorVersion, ModuleClass, SourcedDependency, SourcedWebpack, sourceFramework, sourceHtmlWebpackPlugin, sourceWebpackDevServer } from './sourceRelativeWebpackModules'

Expand Down Expand Up @@ -74,71 +75,12 @@ function getNextJsPackages (devServerConfig: WebpackDevServerConfig) {

/**
* Types for `getNextJsBaseWebpackConfig` based on version:
* - v11.1.4
* - v14.0.0, v15.0.0, and v16.0.0
[
dir: string,
options: {
buildId: string
config: NextConfigComplete
dev?: boolean
isServer?: boolean
pagesDir: string
target?: string
reactProductionProfiling?: boolean
entrypoints: WebpackEntrypoints
rewrites: CustomRoutes['rewrites']
isDevFallback?: boolean
runWebpackSpan: Span
}
]

* - v12.0.0 = Same as v11.1.4

* - v12.1.6
[
dir: string,
options: {
buildId: string
config: NextConfigComplete
compilerType: 'client' | 'server' | 'edge-server'
dev?: boolean
entrypoints: webpack5.EntryObject
hasReactRoot: boolean
isDevFallback?: boolean
pagesDir: string
reactProductionProfiling?: boolean
rewrites: CustomRoutes['rewrites']
runWebpackSpan: Span
target?: string
}
]

* - v13.0.0
[
dir: string,
options: {
buildId: string
config: NextConfigComplete
compilerType: CompilerNameValues
dev?: boolean
entrypoints: webpack.EntryObject
hasReactRoot: boolean
isDevFallback?: boolean
pagesDir?: string
reactProductionProfiling?: boolean
rewrites: CustomRoutes['rewrites']
runWebpackSpan: Span
target?: string
appDir?: string
middlewareMatchers?: MiddlewareMatcher[]
}
]

* - v13.0.1
[
dir: string,
options: {
options: {
buildId: string
encryptionKey: string
config: NextConfigComplete
compilerType: CompilerNameValues
dev?: boolean
Expand All @@ -147,41 +89,27 @@ function getNextJsPackages (devServerConfig: WebpackDevServerConfig) {
pagesDir?: string
reactProductionProfiling?: boolean
rewrites: CustomRoutes['rewrites']
originalRewrites?: CustomRoutes['rewrites']
originalRedirects?: CustomRoutes['redirects']
runWebpackSpan: Span
target?: string
appDir?: string
middlewareMatchers?: MiddlewareMatcher[]
}
]

* - v13.2.1
[
dir: string,
options: {
buildId: string
config: NextConfigComplete
compilerType: CompilerNameValues
dev?: boolean
entrypoints: webpack.EntryObject
isDevFallback?: boolean
pagesDir?: string
reactProductionProfiling?: boolean
rewrites: CustomRoutes['rewrites']
runWebpackSpan: Span
target?: string
appDir?: string
middlewareMatchers?: MiddlewareMatcher[]
noMangling?: boolean
jsConfig: any
resolvedBaseUrl: string | undefined
supportedBrowsers: string[] | undefined
clientRouterFilters?: {
staticFilter: ReturnType<
import('../shared/lib/bloom-filter').BloomFilter['export']
>
dynamicFilter: ReturnType<
import('../shared/lib/bloom-filter').BloomFilter['export']
>
middlewareMatchers?: ProxyMatcher[]
noMangling?: boolean
jsConfig: any
jsConfigPath?: string
resolvedBaseUrl: ResolvedBaseUrl
supportedBrowsers: string[] | undefined
clientRouterFilters?: {
staticFilter: ReturnType<
import('../shared/lib/bloom-filter').BloomFilter['export']
>
dynamicFilter: ReturnType<
import('../shared/lib/bloom-filter').BloomFilter['export']
>
}
fetchCacheKeyPrefix?: string
isCompileMode?: boolean
previewProps: NonNullable<(typeof NextBuildContext)['previewProps']>;
}
}
]
Expand Down Expand Up @@ -210,7 +138,7 @@ async function loadWebpackConfig (devServerConfig: WebpackDevServerConfig): Prom
// Client webpack config for Next.js > 12.1.5
compilerType: 'client',
// Required for Next.js > 13
hasReactRoot: reactVersion === 18,
hasReactRoot: Boolean(reactVersion && reactVersion >= 18),
// Required for Next.js > 13.2.0 to respect TS/JS config
jsConfig: jsConfigResult.jsConfig,
// Required for Next.js > 13.2.0 to respect tsconfig.compilerOptions.baseUrl
Expand Down Expand Up @@ -338,34 +266,23 @@ function sourceNextWebpack (devServerConfig: WebpackDevServerConfig, framework:
throw e
}

// Next 11 allows the choice of webpack@4 or webpack@5, depending on the "webpack5" property in their next.config.js
// The webpackModule.init" for Next 11 returns a webpack@4 or webpack@4 compiler instance based on this boolean
let webpack5 = true
const importPath = path.join(path.dirname(webpackJsonPath), 'webpack.js')
const webpackModule = require(importPath)

try {
const nextConfig = require(path.resolve(devServerConfig.cypressConfig.projectRoot, 'next.config.js'))

debug('NextWebpack: next.config.js found - %o', nextConfig)

if (nextConfig.webpack5 === false) {
webpack5 = false
}
} catch (e) {
// No next.config.js, assume webpack 5
// If Next.js is 16 and greater, webpack.js runs the required code previously inside init() on require().
// init() no longer exists and has the same affect on import, so we don't/can't invoke it
if (semver.lt(framework.packageJson.version, '16.0.0')) {
// for next 15 and down, we need to initialize the webpack module
webpackModule.init(true)
}

debug('NextWebpack: webpack5 - %s', webpack5)
webpackModule.init(webpack5)

const packageJson = require(webpackJsonPath)

webpack.importPath = importPath
// The package.json of "next/dist/compiled/webpack/package.json" has no version so we supply the version for later use
webpack.packageJson = { ...packageJson, version: webpack5 ? '5' : '4' }
webpack.packageJson = { ...packageJson, version: '5' }
webpack.module = webpackModule.webpack
webpack.majorVersion = getMajorVersion(webpack.packageJson, [4, 5])
webpack.majorVersion = getMajorVersion(webpack.packageJson, [5])

debug('NextWebpack: Successfully loaded NextWebpack - %o', webpack)

Expand Down
20 changes: 10 additions & 10 deletions packages/scaffold-config/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,16 @@ We will also attempt to scaffold a configuration file for projects using React a

### Supported Frameworks and Libraries

| Name | Version| Dev Server | Version | Library | Component Adaptor | Example Project |
| ---------------- | -------| ---------- | ---------- | ------------------ | -------------------------- | ------------------------------------------------------------------- |
| React | - | Vite | 5, 6, 7 | React 18, 19 | `@cypress/react@latest` | [Link](../../system-tests/projects/react-vite-ts-configured) |
| React | - | Webpack | 5 | React 18, 19 | `@cypress/vue@latest` | [Link](../../system-tests/projects/react18) |
| Vue | - | Vite | 5, 6, 7 | Vue 3 | `@cypress/react@latest` | [Link](../../system-tests/projects/vue3-vite-ts-configured) |
| Vue | - | Webpack | 5 | Vue 3 | `@cypress/vue@latest` | [Link](../../system-tests/projects/vue3-webpack-ts-configured) |
| Angular | - | Webpack | 5 | Angular 17, 18, 19 | `@cypress/angular@latest` | [Link](../../system-tests/projects/angular-cli-configured) |
| Svelte | - | Vite | 5, 6, 7 | Svelte 5 | `@cypress/svelte@latest` | [Link](../../system-tests/projects/svelte-vite-configured) |
| Svelte | - | Webpack | 5 | Svelte 5 | `@cypress/svelte@latest` | [Link](../../system-tests/projects/svelte-webpack-configured) |
| Next.js | 14, 15 | Webpack | 5 | React 18, 19 | `@cypress/react@latest` | [Link](../../system-tests/projects/nextjs-configured) |
| Name | Version | Dev Server | Version | Library | Component Adaptor | Example Project |
| ---------------- | -----------| ---------- | ---------- | ------------------ | -------------------------- | ------------------------------------------------------------------- |
| React | - | Vite | 5, 6, 7 | React 18, 19 | `@cypress/react@latest` | [Link](../../system-tests/projects/react-vite-ts-configured) |
| React | - | Webpack | 5 | React 18, 19 | `@cypress/vue@latest` | [Link](../../system-tests/projects/react18) |
| Vue | - | Vite | 5, 6, 7 | Vue 3 | `@cypress/react@latest` | [Link](../../system-tests/projects/vue3-vite-ts-configured) |
| Vue | - | Webpack | 5 | Vue 3 | `@cypress/vue@latest` | [Link](../../system-tests/projects/vue3-webpack-ts-configured) |
| Angular | - | Webpack | 5 | Angular 17, 18, 19 | `@cypress/angular@latest` | [Link](../../system-tests/projects/angular-cli-configured) |
| Svelte | - | Vite | 5, 6, 7 | Svelte 5 | `@cypress/svelte@latest` | [Link](../../system-tests/projects/svelte-vite-configured) |
| Svelte | - | Webpack | 5 | Svelte 5 | `@cypress/svelte@latest` | [Link](../../system-tests/projects/svelte-webpack-configured) |
| Next.js | 14, 15, 16 | Webpack | 5 | React 18, 19 | `@cypress/react@latest` | [Link](../../system-tests/projects/nextjs-configured) |

### Adding More Projects

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 @@ -61,7 +61,7 @@ export const WIZARD_DEPENDENCY_NEXT = {
// next 15.0.0 -> 15.0.3 use the React 19 RC as a dependency
// Since we do not support the React 19 RC and only the official React 19 release,
// we will only be supporting Next.js 15.0.4 officially (the others previously mentioned should still work)
minVersion: '^14.0.0 || ^15.0.4',
minVersion: '^14.0.0 || ^15.0.4 || ^16.0.0',
} as const

export const WIZARD_DEPENDENCY_ANGULAR_CLI = {
Expand Down
4 changes: 2 additions & 2 deletions packages/scaffold-config/test/detect.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ describe('detectFramework', () => {
expect(actual.bundler).toEqual('vite')
})

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

fakeDepsInNodeModules(projectPath, [
{ dependency: 'react', version: v === '15.0.0' ? '19.0.0' : '18.0.0' },
{ dependency: 'react', version: '19.0.0' },
{ dependency: 'next', version: v },
])

Expand Down
40 changes: 40 additions & 0 deletions system-tests/projects/next-16-tsconfig-tailwind/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.*
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/versions

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# env files (can opt-in for committing if needed)
.env*

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
36 changes: 36 additions & 0 deletions system-tests/projects/next-16-tsconfig-tailwind/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-app`](https://nextjs.org/docs/app/api-reference/cli/create-next-app).

## Getting Started

First, run the development server:

```bash
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun dev
```

Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.

You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

This project uses [`next/font`](https://nextjs.org/docs/app/building-your-application/optimizing/fonts) to automatically optimize and load [Geist](https://vercel.com/font), a new font family for Vercel.

## Learn More

To learn more about Next.js, take a look at the following resources:

- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.

You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js) - your feedback and contributions are welcome!

## Deploy on Vercel

The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.

Check out our [Next.js deployment documentation](https://nextjs.org/docs/app/building-your-application/deploying) for more details.
Loading
Loading