Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
1 change: 1 addition & 0 deletions cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ _Released 12/16/2025 (PENDING)_

- Fixed an issue where a EPIPE error shows up after CTRL+C is done in terminal. Fixes [#30659](https://github.com/cypress-io/cypress/issues/30659). Addressed in [#32873](https://github.com/cypress-io/cypress/pull/32873).
- Fixed an issue where the browser would freeze when Cypress intercepts a synchronous XHR request and a `routeHandler` is used. Fixes [#32874](https://github.com/cypress-io/cypress/issues/32874). Addressed in [#32925](https://github.com/cypress-io/cypress/pull/32925).
- Fixed an issue where `Next.js` Component Testing would not load correctly without a TypeScript-based Next config in versions 16.0.3 and up. Fixes [#32968](https://github.com/cypress-io/cypress/issues/32968).
- Fixed an issue where the error message for `not.have.length` was not correctly displaying the expected length in the Command Log. Addressed in [#18927](https://github.com/cypress-io/cypress/issues/18927).

## 15.7.1
Expand Down
16 changes: 14 additions & 2 deletions npm/webpack-dev-server/src/helpers/nextHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export async function nextHandler (devServerConfig: WebpackDevServerConfig): Pro
* `loadConfig` acquires the next.config.js
* `getNextJsBaseWebpackConfig` acquires the webpackConfig dependent on the next.config.js
*/
function getNextJsPackages (devServerConfig: WebpackDevServerConfig) {
async function getNextJsPackages (devServerConfig: WebpackDevServerConfig) {
const resolvePaths = { paths: [devServerConfig.cypressConfig.projectRoot] }
const packages = {} as {
loadConfig: (phase: 'development', dir: string) => Promise<any>
Expand All @@ -37,6 +37,18 @@ function getNextJsPackages (devServerConfig: WebpackDevServerConfig) {
getSupportedBrowsers: (dir: string, isDevelopment: boolean, nextJsConfig: any) => Promise<string[] | undefined>
}

// Starting with Next.js 16.0.3, we need to proactively install SWC bindings
// See: https://github.com/vercel/next.js/pull/85787
try {
const installBindingsPath = require.resolve('next/dist/build/swc/install-bindings', resolvePaths)
const { installBindings } = require(installBindingsPath)

await installBindings()
} catch (e: any) {
// installBindings doesn't exist in Next.js < 16.0.3, which is fine
debug('installBindings not available (Next.js < 16.0.3): %s', e.message ?? e)
}

try {
const loadConfigPath = require.resolve('next/dist/server/config', resolvePaths)

Expand Down Expand Up @@ -115,7 +127,7 @@ function getNextJsPackages (devServerConfig: WebpackDevServerConfig) {
]
*/
async function loadWebpackConfig (devServerConfig: WebpackDevServerConfig): Promise<Configuration> {
const { loadConfig, getNextJsBaseWebpackConfig, nextLoadJsConfig, getSupportedBrowsers } = getNextJsPackages(devServerConfig)
const { loadConfig, getNextJsBaseWebpackConfig, nextLoadJsConfig, getSupportedBrowsers } = await getNextJsPackages(devServerConfig)

const nextConfig = await loadConfig('development', devServerConfig.cypressConfig.projectRoot)
const runWebpackSpan = getRunWebpackSpan(devServerConfig)
Expand Down
1 change: 1 addition & 0 deletions system-tests/projects/nextjs-configured/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
NOTE: this project implicitly tests the fix for https://github.com/cypress-io/cypress/issues/32968 as we need to call `installBindings()` inside `npm/webpack-dev-server/src/helpers/nextHandler.ts` for Next 16.0.3+.
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React from 'react'
import { mount } from 'cypress/react'
import { Button } from './button'

it('works', () => {
mount(<Button />)
cy.mount(<Button />)
cy.get('button').contains('Hello World')
})
17 changes: 14 additions & 3 deletions system-tests/projects/nextjs-configured/cypress.config.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,20 @@
module.exports = {
import { defineConfig } from 'cypress'
import path from 'path'

export default defineConfig({
fixturesFolder: false,
component: {
experimentalSingleTabRunMode: true,
devServer: {
framework: 'next',
bundler: 'webpack',
webpackConfig: {
resolve: {
alias: {
'react': path.resolve(__dirname, './node_modules/react'),
'react-dom': path.resolve(__dirname, './node_modules/react-dom'),
},
},
},
},
},
}
})
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// ***********************************************************
// This example support/component.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************

// Import commands.js using ES2015 syntax:
import './commands'

import { mount } from 'cypress/react'

Cypress.Commands.add('mount', mount)

// Example use:
// cy.mount(<MyComponent />)
9 changes: 9 additions & 0 deletions system-tests/projects/nextjs-configured/jsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"compilerOptions": {
"paths": {
"@/*": [
"./src/*"
]
}
}
}
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/** @type {import('next').NextConfig} */
const nextConfig = {
webpack5: true,
/* config options here */
reactStrictMode: true,
}

module.exports = nextConfig
export default nextConfig
16 changes: 4 additions & 12 deletions system-tests/projects/nextjs-configured/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,12 @@
"scripts": {
"build": "next build",
"dev": "next dev",
"lint": "next lint",
"start": "next start"
},
"dependencies": {
"next": "^15.2.3",
"react": "18.3.1",
"react-dom": "18.3.1"
"next": "16.0.7",
"react": "19.2.0",
"react-dom": "19.2.0"
},
"devDependencies": {
"@cypress/webpack-dev-server": "file:../../../npm/webpack-dev-server",
"eslint": "8.9.0",
"eslint-config-next": "15.2.3",
"html-webpack-plugin": "^5.6.3",
"webpack": "^5.91.0",
"webpack-dev-server": "^5.1.0"
}
"type": "module"
}
7 changes: 0 additions & 7 deletions system-tests/projects/nextjs-configured/pages/_app.js

This file was deleted.

69 changes: 0 additions & 69 deletions system-tests/projects/nextjs-configured/pages/index.js

This file was deleted.

1 change: 1 addition & 0 deletions system-tests/projects/nextjs-configured/public/file.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions system-tests/projects/nextjs-configured/public/globe.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions system-tests/projects/nextjs-configured/public/next.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 1 addition & 4 deletions system-tests/projects/nextjs-configured/public/vercel.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions system-tests/projects/nextjs-configured/public/window.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions system-tests/projects/nextjs-configured/src/pages/_app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import '@/styles/globals.css'

export default function App ({ Component, pageProps }) {
return <Component {...pageProps} />
}
13 changes: 13 additions & 0 deletions system-tests/projects/nextjs-configured/src/pages/_document.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Html, Head, Main, NextScript } from 'next/document'

export default function Document () {
return (
<Html lang="en">
<Head />
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
88 changes: 88 additions & 0 deletions system-tests/projects/nextjs-configured/src/pages/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import Head from 'next/head'
import Image from 'next/image'
import { Geist, Geist_Mono } from 'next/font/google'
import styles from '@/styles/Home.module.css'

const geistSans = Geist({
variable: '--font-geist-sans',
subsets: ['latin'],
})

const geistMono = Geist_Mono({
variable: '--font-geist-mono',
subsets: ['latin'],
})

export default function Home () {
return (
<>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="icon" href="/favicon.ico" />
</Head>
<div
className={`${styles.page} ${geistSans.variable} ${geistMono.variable}`}
>
<main className={styles.main}>
<Image
className={styles.logo}
src="/next.svg"
alt="Next.js logo"
width={100}
height={20}
priority
/>
<div className={styles.intro}>
<h1>To get started, edit the index.js file.</h1>
<p>
Looking for a starting point or more instructions? Head over to{' '}
<a
href="https://vercel.com/templates?framework=next.js&utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Templates
</a>{' '}
or the{' '}
<a
href="https://nextjs.org/learn?utm_source=create-next-app&utm_medium=appdir-template-tw&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Learning
</a>{' '}
center.
</p>
</div>
<div className={styles.ctas}>
<a
className={styles.primary}
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
<Image
className={styles.logo}
src="/vercel.svg"
alt="Vercel logomark"
width={16}
height={16}
/>
Deploy Now
</a>
<a
className={styles.secondary}
href="https://nextjs.org/docs?utm_source=create-next-app&utm_medium=appdir-template&utm_campaign=create-next-app"
target="_blank"
rel="noopener noreferrer"
>
Documentation
</a>
</div>
</main>
</div>
</>
)
}
Loading